bzoj3994: [SDOI2015]約數個數和(莫比烏斯反演+分塊)
阿新 • • 發佈:2018-05-30
put name 一行 AI algorithm scan space 代碼 print
www.cnblogs.com/shaokele/
bzoj3994: [SDOI2015]約數個數和
Time Limit: 20 Sec
Memory Limit: 128 MBDescription
設d(x)為x的約數個數,給定N、M,求 \(\sum_{i=1}^{n}\sum_{j=1}^{m}d(i j)\)
Input
輸入文件包含多組測試數據。
第一行,一個整數T,表示測試數據的組數。
接下來的T行,每行兩個整數N、M。
Output
T行,每行一個整數,表示你所求的答案。
Sample Input
2
7 4
5 6
Sample Output
110
121
題目地址: bzoj3994: [SDOI2015]約數個數和
題目大意: 題目很簡潔了:)
題解:
莫比烏斯反演
初寫莫隊可以先切這題
AC代碼
#include <cstdio> #include <algorithm> #define ll long long using namespace std; const int N=500005; int n,m,Q,tot; int u[N],f[N],g[N],pri[N]; bool fl[N]; inline void init(){ u[1]=f[1]=1; for(int i=2;i<=N;i++){ if(!fl[i]){ pri[++tot]=i; g[i]=1; u[i]=-1; f[i]=2; } for(int j=1;j<=tot && i*pri[j]<=N;j++){ fl[i*pri[j]]=1; if(i%pri[j]==0){ g[i*pri[j]]=g[i]+1; u[i*pri[j]]=0; f[i*pri[j]]=f[i]/(g[i]+1)*(g[i]+2); }else{ g[i*pri[j]]=1; u[i*pri[j]]=-u[i]; f[i*pri[j]]=f[i]*2; } } } for(int i=2;i<=N;i++) f[i]+=f[i-1],u[i]+=u[i-1]; } int main(){ init(); scanf("%d",&Q); while(Q--){ scanf("%d%d",&n,&m); if(n>m)swap(n,m); ll ans=0; int l,r; for(l=1;l<=n;l=r+1){ r=min(n/(n/l),m/(m/l)); ans+=(ll)(u[r]-u[l-1])*f[n/l]*f[m/l]; } printf("%lld\n",ans); } return 0; }
bzoj3994: [SDOI2015]約數個數和(莫比烏斯反演+分塊)