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 }
View Code
原文地址:https://www.cnblogs.com/oldjang/p/6750144.html