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  }

 

 

你可能感兴趣的:(ural 1907容斥原理)