[BZOJ4772]显而易见的数论(数论)
4772: 显而易见的数论
Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 76 Solved: 32
[Submit][Status][Discuss]Description
Input
Output
Sample Input
input 1
1
3 3
0 1 2
input 2
2
5 4
4 1 5 2
input 3
3
7 5
12 11 45 6 2
Sample Output
output 1
4
output 2
31
output 3
7346HINT
Source
[Submit][Status][Discuss]
预处理即$O(1)$求$F$显然不是瓶颈,关键是g和最终答案的求法。
比较自然的思路是枚举$p_i$,$p_j$,算出它们的出现次数和贡献,累计结果。
这个分情况讨论,整数划分DP一下就好了。
https://www.cnblogs.com/xiaoxubi/p/6927810.html
然后根据一波迷之推导得出$g$是一个积性函数,这样线性筛预处理即可。
https://blog.csdn.net/v5zsq/article/details/76714310
这样时间复杂度问题方面就解决了,然而这题卡时卡空间,任何一个取模运算较多的操作都有可能超时。
可以看出$p_i\neq p_j$的常数过大,所以用$cnt$数组先统计出$a[i]$一共被累计了几次,最后一起乘起来就好了。
1 #include<cstdio> 2 #include<algorithm> 3 #define rep(i,l,r) for (int i=l; i<=r; i++) 4 using namespace std; 5 6 const int N=2010,M=10000010,mod=1000000007; 7 int type,n,K,tot,ans,gcd[N][N],f[N][N],sum[N],mul[N][N]; 8 int tmp[M],cnt[M],g[M],pri[M],a[M]; 9 bool jud[M]; 10 11 void add(int &x,int y){ x+=y; if (x>=mod) x-=mod; } 12 13 void pre1(){ 14 sum[n]=1; 15 rep(i,1,n) rep(j,1,n){ 16 if (i==1 || j==1) f[i][j]=1; 17 else if (j==i) f[i][j]=(f[i][j-1]+1)%mod; 18 else if (j<i) f[i][j]=(f[i-j][j]+f[i][j-1])%mod; 19 else f[i][j]=f[i][j-1]; 20 sum[n-i]=f[i][i]; 21 } 22 } 23 24 void pre2(){ 25 g[0]=0; g[1]=1; 26 rep(i,2,10000000){ 27 if (!jud[i]) pri[++tot]=tmp[i]=i,g[i]=(2*i-2)%mod; 28 for (int j=1; j<=tot && i*pri[j]<=M; j++){ 29 jud[i*pri[j]]=1; 30 if (i%pri[j]) tmp[i*pri[j]]=pri[j],g[i*pri[j]]=g[i]*g[pri[j]]%mod; 31 else{ 32 tmp[i*pri[j]]=tmp[i]*pri[j]; 33 if (tmp[i]!=i) g[i*pri[j]]=1ll*g[i/tmp[i]]*g[tmp[i]*pri[j]]%mod; 34 else g[i*pri[j]]=(1ll*g[i]*pri[j]+i*pri[j]-i)%mod; 35 break; 36 } 37 } 38 } 39 } 40 41 void pre3(){ 42 rep(i,1,n) gcd[i][0]=gcd[0][i]=gcd[i][i]=i,gcd[1][i]=gcd[i][1]=1; 43 rep(i,2,n) rep(j,2,i){ 44 if (!gcd[i][j]) gcd[i][j]=gcd[j][i-j]; 45 gcd[j][i]=gcd[i][j]; 46 } 47 rep(i,1,n){ 48 mul[i][0]=1; 49 rep(j,1,n) mul[i][j]=1ll*mul[i][j-1]*i%K; 50 } 51 } 52 53 int F(int pi,int pj){ 54 if (type==1) return 1%K; 55 if (type==2) return gcd[pi][pj]%K; 56 if (type==3) return (mul[pi][pj]+mul[pj][pi]+(pi^pj))%K; 57 return 0; 58 } 59 60 int main(){ 61 freopen("bzoj4772.in","r",stdin); 62 freopen("bzoj4772.out","w",stdout); 63 scanf("%d%d%d",&type,&n,&K); 64 for (int i=0; i<K; i++) scanf("%d",&a[i]); 65 pre1(); pre2(); pre3(); 66 /* 67 rep(i,1,n) rep(j,i+1,n-i) 68 for (int muli=1; i*muli<=n-j; muli++) 69 for (int mulj=1; i*muli+j*mulj<=n; mulj++){ 70 int t=(sum[muli*i+mulj*j]-sum[(muli+1)*i+mulj*j]-sum[muli*i+(mulj+1)*j]+sum[(muli+1)*i+(mulj+1)*j])%mod; 71 add(cnt[F(i,j)],1ll*muli*mulj*(t+mod)%mod); 72 } 73 */ 74 rep(i,1,n) rep(j,i+1,n-i) 75 for (int muli=1; i*muli<=n-j; muli++) 76 for (int mulj=1; i*muli+j*mulj<=n; mulj++) add(cnt[F(i,j)],sum[muli*i+mulj*j]); 77 for (int i=0; i<K; i++) add(ans,1ll*g[a[i]]*cnt[i]%mod); 78 rep(i,1,n) for (int muli=1; i*muli<=n; muli++) 79 add(ans,(1ll*g[a[F(i,i)]]*((muli*(muli-1)/2)%mod))%mod*(sum[muli*i]-sum[(muli+1)*i]+mod)%mod); 80 printf("%d\n",ans); 81 return 0; 82 }