bzoj 2818 gcd 线性欧拉函数
2818: Gcd
Time Limit: 10 Sec Memory Limit: 256 MB[Submit][Status][Discuss]
Description
给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.
Input
一个整数N
Output
如题
Sample Input
4
Sample Output
4
HINT
hint
对于样例(2,2),(2,4),(3,3),(4,2)
1<=N<=10^7
思路:gcd(x,y)=p;p为素数;
gcd(x/p,y/p)==1;
一个p的贡献为1-(N/p),求前缀和意思;
#include<bits/stdc++.h> using namespace std; #define ll long long #define mod 1000000009 #define inf 999999999 #define esp 0.00000000001 //#pragma comment(linker, "/STACK:102400000,102400000") const int N=1e5,M=1e7+1000; ll p[M],ji; bool vis[M]; ll phi[M]; void get_eular(int n) { ji = 0; memset(vis, true, sizeof(vis)); for(int i = 2; i <= n; i++) { if(vis[i]) { p[ji ++] = i; phi[i] = i - 1; } for(int j = 0; j < ji && i * p[j] <= n; j++) { vis[i * p[j]] = false; if(i % p[j] == 0) { phi[i * p[j]] = phi[i] * p[j]; break; } else phi[i * p[j]] = phi[i] * phi[p[j]]; } } } ll sumphi[M]; int main() { ll x,y,z,i,t; get_eular(10000100); sumphi[0]=1; for(i=1;i<=10000000;i++) sumphi[i]=sumphi[i-1]+phi[i]; while(~scanf("%lld",&x)) { ll ans=0; for(i=0;p[i]<=x;i++) ans+=2*sumphi[x/p[i]]-1; printf("%lld\n",ans); } return 0; }