很容易得出暴力DP方程。。
d[i][j][k][v]=d[i-1][k][v][t]*gcd(j,k,v,t) v=1..m
其中j,k,v,t就是i位前的4个数字。。
显然炸到飞起。。需要优化。。
然后这次是从状态设计上进行优化。。
由于关注的只是gcd(j,k,v,t)所以考虑直接维护gcd(k,v,t),转移的时候发现要维护gcd(k,v,t)需要维护gcd(k,v)进一步需要维护k。。
然后状态就变成了d[i][k][gcd(k,v)][gcd(k,v,t)]。。貌似和原来没什么不同不过由于整除关系,有效状态数只要1000多。。然后就可以写了。。
代码奇丑无比。。
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━━━━━━━━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1LL<<(x))
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 105
#define nm 2005
#define N 1000005
#define M(x,y) x=max(x,y)
const double pi=acos(-1);
const ll inf=1e9+7;
using namespace std;
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
struct tmp{int x,y,z;}c[nm];
int n,m,a[NM],v[NM],b[NM][NM][NM],tot,g[NM][NM];
ll f[NM][nm],ans,inv;
ll qpow(ll x,ll t){return t?qpow(sqr(x)%inf,t>>1)*(t&1?x:1)%inf:1LL;}
int main(){
inc(i,1,100)inc(j,1,100)g[i][j]=__gcd(i,j);
int _=read();while(_--){
ans=0;mem(f);mem(c);mem(b);tot=0;
n=read();m=read();inv=qpow(m,inf-2);
inc(i,1,m)inc(j,1,i)inc(k,1,j)if(i%j==0&&j%k==0)c[++tot]={i,j,k},b[i][j][k]=tot;
//printf("%d\n",tot);
inc(i,1,n)a[i]=read();
inc(i,1,m)v[i]=read();
ll _t=1;
inc(i,1,3)if(!a[i])_t=inv*_t%inf;
inc(i,1,m)if(!a[1]||a[1]==i)inc(j,1,m)if(!a[2]||a[2]==j)inc(k,1,m)if(!a[3]||a[3]==k)
(f[3][b[k][g[k][j]][g[k][g[i][j]]]]+=_t)%=inf;
inc(i,4,n)if(a[i]){
inc(j,1,tot)
(f[i][b[a[i]][g[a[i]][c[j].x]][g[a[i]][c[j].y]]]+=f[i-1][j]*v[g[a[i]][c[j].z]])%=inf;
}else{
inc(j,1,tot)inc(k,1,m)
(f[i][b[k][g[k][c[j].x]][g[k][c[j].y]]]+=inv*f[i-1][j]%inf*v[g[k][c[j].z]])%=inf;
}
inc(j,1,tot)ans+=f[n][j],ans%=inf;
printf("%lld\n",ans);
}
return 0;
}
Problem I. Random Sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 108 Accepted Submission(s): 32
Problem Description
There is a positive integer sequence a1,a2,...,an with some unknown positions, denoted by 0. Little Q will replace each 0 by a random integer within the range [1,m] equiprobably. After that, he will calculate the value of this sequence using the following formula :
∏i=1n−3v[gcd(ai,ai+1,ai+2,ai+3)]
Little Q is wondering what is the expected value of this sequence. Please write a program to calculate the expected value.
Input
The first line of the input contains an integer T(1≤T≤10), denoting the number of test cases.
In each test case, there are 2 integers n,m(4≤n≤100,1≤m≤100) in the first line, denoting the length of the sequence and the bound of each number.
In the second line, there are n integers a1,a2,...,an(0≤ai≤m), denoting the sequence.
In the third line, there are m integers v1,v2,...vm(1≤vi≤109), denoting the array v.
Output
For each test case, print a single line containing an integer, denoting the expected value. If the answer is AB, please print C(0≤C<109+7) where A≡C×B(mod109+7).
Sample Input
2 6 8 4 8 8 4 6 5 10 20 30 40 50 60 70 80 4 3 0 0 0 0 3 2 4
Sample Output
8000 3
Source
2018 Multi-University Training Contest 3
Recommend
chendu | We have carefully selected several similar problems for you: 6331 6330 6329 6328 6327
Statistic | Submit | Discuss | Note