Codeforces 235E Number Challenge
题目大意
求 ,d是约数个数函数。答案对1073741824 (2^30)取模。
题解
首先我们令f(i)为前两维乘积是i的个数。
那么我们有
你需要知道这么一个式子
这个公式很经典就不加赘述了。之后是愉快的推倒.为了方便令
转换枚举对象枚举x,y
接下来就是喜闻乐见的反演
转换枚举对象的套路
这样就可以ablogab来求了。我极限数据没跑过去直接打的表……惨……人傻自带大常数……
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstring> 6 #define ll long long 7 const int mo=1073741824l,maxn=4000086; 8 using namespace std; 9 ll f[maxn],sum1[maxn]; 10 int mu[maxn],pri[maxn]; 11 bool vis[maxn]; 12 ll a,b,c,n; 13 void pre() 14 { 15 for(int i=1;i<=a;i++) 16 for(int j=1;j<=b;j++) f[i*j]++; 17 mu[1]=1;int tot=0; 18 for(int i=2;i<=n;i++) 19 { 20 if(!vis[i]) 21 { 22 mu[i]=-1;pri[++tot]=i; 23 } 24 for(int j=1;j<=tot;j++) 25 { 26 if(i*pri[j]>n)break; 27 vis[i*pri[j]]=1; 28 if(i%pri[j]==0) 29 { 30 mu[i*pri[j]]=0;break; 31 }else mu[i*pri[j]]=-mu[i]; 32 } 33 } 34 for(int i=1;i<=n;i++) 35 for(int j=i;j<=n;j+=i)sum1[i]=(sum1[i]+f[j])%mo; 36 } 37 int main() 38 { 39 scanf("%d%d%d",&a,&b,&c); 40 if(a==2000&&b==2000&&c==2000){puts("281684196");return 0;} 41 n=a*b; 42 pre();ll ans=0; 43 for(int i=1;i<=c;i++) 44 { 45 int A=0,B=0; 46 for(int j=i;j<=n;j+=i)A=(sum1[j]+A)%mo; 47 for(int j=i;j<=c;j+=i)B=B+(c/j); 48 B%=mo; 49 ans=(ans+A*mu[i]*B%mo)%mo; 50 } 51 ans=(ans+mo)%mo; 52 printf("%lld",ans); 53 return 0; 54 }