跳蚤 POJ - 1091
考察:容斥原理
迷惑数据,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 }