BZOJ3994: [SDOI2015]约数个数和(莫比乌斯反演)
Description
设d(x)为x的约数个数,给定N、M,求
Input
输入文件包含多组测试数据。
第一行,一个整数T,表示测试数据的组数。
接下来的T行,每行两个整数N、M。
Output
T行,每行一个整数,表示你所求的答案。
Sample Input
2
7 4
5 6
7 4
5 6
Sample Output
110
121
121
解题思路:
有一个喜闻乐见的结论:
${\sum_{i=1}^{n}}{\sum_{j=1}^{m}}{d(i*j)]}={\sum_{i=1}^{n}}{\sum_{j=1}^{m}}[gcd(i,j)==1]{\left \lfloor \frac{N}{i} \right \rfloor}{\left \lfloor \frac{M}{j} \right \rfloor}$
剩下的大家都会了吧QAQ
代码:
1 #include<map> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 const int N=3000000; 6 struct lnt{ 7 std::map<unsigned int,long long>Arr; 8 long long arr[N]; 9 bool has[N]; 10 void Insert(unsigned int x,long long y) 11 { 12 if(x<N) 13 arr[x]=y,has[x]=true; 14 else 15 Arr[x]=y; 16 } 17 bool find(unsigned int x) 18 { 19 if(x<N) 20 return has[x]; 21 else 22 return Arr.find(x)!=Arr.end(); 23 } 24 long long val(unsigned int pos) 25 { 26 if(pos<N) 27 return arr[pos]; 28 return Arr[pos]; 29 } 30 }; 31 unsigned int prime[N]; 32 int phi[N]; 33 int miu[N]; 34 bool vis[N]; 35 unsigned int cnt; 36 lnt Sum_phi; 37 lnt Sum_miu; 38 void gtp(void) 39 { 40 miu[1]=phi[1]=1; 41 Sum_phi.Insert(0,0); 42 Sum_miu.Insert(0,0); 43 for(int i=2;i<N;i++) 44 { 45 if(!vis[i]) 46 { 47 prime[++cnt]=i; 48 miu[i]=-1; 49 phi[i]=i-1; 50 } 51 for(int j=1;j<=cnt&&i*prime[j]<N;j++) 52 { 53 vis[i*prime[j]]=true; 54 if(i%prime[j]==0) 55 { 56 miu[i*prime[j]]=0; 57 phi[i*prime[j]]=phi[i]*prime[j]; 58 break; 59 } 60 miu[i*prime[j]]=-miu[i]; 61 phi[i*prime[j]]=phi[i]*(prime[j]-1); 62 } 63 } 64 for(int i=1;i<N;i++) 65 { 66 Sum_phi.Insert(i,Sum_phi.val(i-1)+phi[i]); 67 Sum_miu.Insert(i,Sum_miu.val(i-1)+miu[i]); 68 } 69 return ; 70 } 71 long long PHI_search(unsigned int pos) 72 { 73 if(Sum_phi.find(pos)) 74 return Sum_phi.val(pos); 75 long long tmp=0; 76 for(unsigned int i=2,j;i<=pos;i=j+1) 77 { 78 j=pos/(pos/i); 79 tmp+=PHI_search(pos/i)*(long long)(j-i+1); 80 } 81 Sum_phi.Insert(pos,1ll*pos*(pos+1)/2-tmp); 82 return 1ll*pos*(pos+1)/2-tmp; 83 } 84 long long MIU_search(unsigned int pos) 85 { 86 if(Sum_miu.find(pos)) 87 return Sum_miu.val(pos); 88 long long tmp=0; 89 for(unsigned int i=2,j;i<=pos;i=j+1) 90 { 91 j=pos/(pos/i); 92 tmp+=(j-i+1)*MIU_search(pos/i); 93 } 94 Sum_miu.Insert(pos,1-tmp); 95 return 1-tmp; 96 } 97 int main() 98 { 99 gtp(); 100 int T; 101 scanf("%d",&T); 102 while(T--) 103 { 104 int x; 105 scanf("%d",&x); 106 printf("%lld %lld\n",PHI_search(x),MIU_search(x)); 107 } 108 return 0; 109 }