标签:
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
By YJQ 我们令dp[i][j]表示在前i个数中,选出若干个数使得它们的gcd为j的方案数,于是只需要枚举第i+1个数是否被选中来转移就可以了
令第i+1个数为v,当考虑dp[i][j]的时候,我们令dp[i+1][j] += dp[i][j]dp[i+1][j]+=dp[i][j](v 不选),dp[i+1][gcd(j,v)] += dp[i][j]dp[i+1][gcd(j,v)]+=dp[i][j](v 选)
复杂度O(N*MaxV) MaxV 为出现过的数的最大值
ps:取模的那个数是坑点。。。。平常是1e9+7。。。
#include<bits/stdc++.h> using namespace std; #define ll __int64 #define mod 100000007 #define esp 0.00000000001 const int N=1e3+10,M=1e6+10,inf=1e9; ll dp[N][N]; int a[N]; int flag[N][N]; int gcd(int x,int y) { return y==0?x:gcd(y,x%y); } int main() { int x,y,z,i,t; for(i=1;i<=1000;i++) for(t=1;t<=1000;t++) flag[i][t]=gcd(i,t); int T; scanf("%d",&T); while(T--) { memset(dp,0,sizeof(dp)); int maxx=0; scanf("%d",&x); for(i=1;i<=x;i++) { scanf("%d",&a[i]); maxx=max(a[i],maxx); } for(i=1;i<=x;i++) { dp[i][a[i]]+=1; for(t=1;t<=maxx;t++) { dp[i][t]+=dp[i-1][t]; dp[i][t]%=mod; dp[i][flag[t][a[i]]]+=dp[i-1][t]; dp[i][flag[t][a[i]]]%=mod; } } ll ans=0; for(ll i=1;i<=maxx;i++) { ans+=(i*dp[x][i])%mod; ans%=mod; } printf("%I64d\n",ans); } return 0; }
标签:
原文地址:http://www.cnblogs.com/jhz033/p/5635823.html