原题链接

考察:容斥原理

迷惑数据,108x15,我寻思这不要高精度?结果网上全是long long就过了...

思路:

      观察发现如果能完成任务,那么n+1数字里至少有一对gcd是1,这样不好考虑,但碰到"至少一对"这种词语可以考虑补集思想,即没有一对公约数为1.这样就转化成求M的质因数...然后计算1~m中有多少个是质因数的倍数的.

易错:

      不能求m的约数,因为约数eg:2 4 8,再计算2的时候已经把后面算了一遍,如果用约数应该将乘法换成lcm

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 using namespace std;
 5 typedef long long ll;
 6 const int N = 1600;
 7 int divs[N],cnt;
 8 ll qsm(ll a,ll k)
 9 {
10     ll res = 1;
11     while(k)
12     {
13         if(k&1) res = res*a;
14         k>>=1;
15         a = a*a; 
16     }
17     return res;
18 }
19 void  GetDivide(int n)
20 {
21     for(int i=2;i<=n/i;i++)
22     {
23         if(n%i==0)
24         {
25             divs[cnt++] = i;
26             while(n%i==0) n/=i;
27         }
28     }
29     if(n>1) divs[cnt++] = n;
30 }
31 int main() 
32 {
33     int n,m;
34     scanf("%d%d",&n,&m);
35     GetDivide(m);
36     ll ans = 0;
37     for(int i=1;i<1<<cnt;i++)
38     {
39         ll res = 1; int k = 0;
40         for(int j=0;j<cnt;j++)
41         {
42             if(i>>j&1)
43             {
44                 if(res*divs[j]>m){ res = -1; break;  } 
45                 res*=divs[j];
46                 k++;
47             }
48         }
49         if(res==-1) continue;
50         if(k&1) ans+=qsm(m/res,n);
51         else ans-=qsm(m/res,n);
52     }
53     printf("%lld",qsm(m,n)-ans);
54     return 0;
55 }