BZOJ#4407. 於神之怒加強版
阿新 • • 發佈:2018-05-27
預處理 code line scrip scanf 約束 eight spa 只需要
Submit: 1302 Solved: 582
1 2
3 3
problem:
求: solution: 預處理出h數組,實現的復雜度 推導:
因為積性函數的約束和也是積性函數,所以h是積性函數:
4407: 於神之怒加強版
Time Limit: 80 Sec Memory Limit: 512 MBSubmit: 1302 Solved: 582
Description
給下N,M,K.求Input
輸入有多組數據,輸入數據的第一行兩個正整數T,K,代表有T組數據,K的意義如上所示,下面第二行到第T+1行,每行為兩個正整數N,M,其意義如上式所示。Output
如題Sample Input
3 3
Sample Output
20HINT
1<=N,M,K<=5000000,1<=T<=2000
problem:
求: solution: 預處理出h數組,實現的復雜度 推導:
枚舉gcd:
套路化解:
根據公式二:
套路枚舉dx:
考慮預處理出:
化解一下:
線性篩時預處理出h數組: 註意: 如果i%prime[j]==0:則μ(i*prime[j])及以後都為0,不再為h做出貢獻,只有D為變。
我們只需要合並時把h乘上一個即可 否則,根據積性函數性質:h(i*prime[j])=h(i)*h(prime[j]),更新即可。
void getmu() { h[1]=1; for(inti=2;i<=N;i++) { if(!vis[i]) { prime[++cnt]=i; g[i]=qpow(k,i); h[i]=(g[i]-1+mod)%mod; } for(int j=1;j<=cnt;j++) { if(i*prime[j]>N) break; vis[i*prime[j]]=1; if(i%prime[j]==0) {h[i*prime[j]]=(h[i]*g[prime[j]])%mod;break;} h[i*prime[j]]=(h[i]*h[prime[j]])%mod; } } for(int i=1;i<=N;i++) h[i]=(h[i]+h[i-1])%mod; }
附上代碼:
#include<bits/stdc++.h> using namespace std; const int N=5e6+12; const int mod=1e9+7; int prime[N],cnt,vis[N]; long long h[N],g[N];//註意long long long long k; int n,m; int qpow(int a,long long b) { long long ans=1; while(a) { if(a&1) ans=ans*b%mod; b=b*b%mod; a>>=1; } ans%=mod; return ans; } void getmu() { h[1]=1; for(int i=2;i<=N;i++) { if(!vis[i]) { prime[++cnt]=i; g[i]=qpow(k,i); h[i]=(g[i]-1+mod)%mod; } for(int j=1;j<=cnt;j++) { if(i*prime[j]>N) break; vis[i*prime[j]]=1; if(i%prime[j]==0) {h[i*prime[j]]=(h[i]*g[prime[j]])%mod;break;} h[i*prime[j]]=(h[i]*h[prime[j]])%mod; } } for(int i=1;i<=N;i++) h[i]=(h[i]+h[i-1])%mod; } int main() { freopen("a.in","r",stdin); int T;scanf("%d%d",&T,&k); getmu(); while(T--) { scanf("%d%d",&n,&m); if(n>m) swap(n,m); int pos; long long ans=0; for(int i=1;i<=n;i=pos+1) { pos=min(n/(n/i),m/(m/i)); long long t=(long long)(n/i)*(m/i)%mod; ans=(ans+(long long)t*(h[pos]-h[i-1]+mod)%mod)%mod; } ans=(ans%mod+mod)%mod; printf("%lld\n",ans); } return 0; }
BZOJ#4407. 於神之怒加強版