ural 1907容斥原理
题意: 给出一个a和n,现在想要知道有多少个i满足 a^2+i^2 与4(a+i)有大于1的公约数; i<=n;
思路 : 首先把 a^2+i^2 转换成(a+i)^2 - 2*a*i. 如果a与i有大于1的公约数那么(a+i)^2 - 2*a*i与4(a+i)就有大于1的公约数。 但是还可以利用4找公约数。 首先利用4找公约数, 然后再利用a*i找(出去4的影响),用a*i找的方法是容斥原理。
AC代码:
View Code
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <cstdio> 5 using namespace std; 6 typedef long long LL; 7 const int N = 1010000; 8 9 LL p[N], num, my[N], mn; 10 bool in[N]; 11 LL a, n; 12 13 void getp() 14 { 15 num = 0; 16 for(int i=2; i<N; i++) 17 { 18 if(!in[i]) 19 { 20 p[num++] = i; 21 for(int j=i; j<N; j+=i) 22 in[j] = 1; 23 } 24 } 25 } 26 27 void getin(LL a) 28 { 29 mn = 0; 30 for(int i=0; i<num && p[i]*p[i]<=a; i++) 31 { 32 if(a%p[i] == 0) 33 { 34 my[mn++] = p[i]; 35 while(a%p[i] == 0) 36 a /= p[i]; 37 } 38 } 39 if(a > 1) 40 { 41 my[mn++] = a; 42 } 43 } 44 45 void solve() 46 { 47 LL ans = 0, tp, cc; 48 if(a%2) 49 ans += n/2 + n%2; 50 else ans += n/2; 51 52 for(int i=1; i<(1<<mn); i++) 53 { 54 tp = 1; 55 cc = 0; 56 for(int j=0; j<mn; j++) 57 { 58 if((1<<j)&i) 59 { 60 tp *= my[j]; 61 cc++; 62 } 63 } 64 //if(tp == 2) continue; 65 if(cc%2) 66 { 67 if(a%2 == 0) 68 { 69 if(tp%2 == 1) 70 ans += n/tp/2 + n/tp%2; 71 } 72 else 73 { 74 if(tp%2 == 0) 75 ans += n/tp; 76 else if(tp%2 == 1) 77 ans += n/tp/2; 78 } 79 } 80 else 81 { 82 if(a%2 == 0) 83 { 84 if(tp%2 == 1) 85 ans -= n/tp/2 + n/tp%2; 86 } 87 else 88 { 89 if(tp%2 == 0) 90 ans -= n/tp; 91 else if(tp%2 == 1) 92 ans -= n/tp/2; 93 } 94 } 95 } 96 cout<<ans<<endl; 97 } 98 99 int main() 100 { 101 getp(); 102 while(scanf("%I64d%I64d", &a, &n) != EOF) 103 { 104 getin(a); 105 solve(); 106 } 107 return 0; 108 }


浙公网安备 33010602011771号