题目链接:http://codeforces.com/contest/955/problem/C
题意:Q次询问,每次询问L,R区间内满足x=a^p的数的个数,其中Q<=1e5,1<=L<=R<=1e18,a>0,p>1;
分析:看到这题首先想到的是分解指数,即在1e18范围内,指数p最大为64(2^64),然后我们可以利用二分将指数为i的满足L<=a^i<=R中a的数求出来(二分的时候注意上界,小心爆long long)。然后用我们考虑对于这2到64的指数中,重复出现的数字有多少个。对于指数为2和指数为3满足的数字,我们可以认为指数为6满足的数字是即满足指数为2,又满足指数为3,因此当我们对指数2和3的数字求和时,我们需要减去指数为6的数字,由此我们可以想到对于2到64以内的素数指数利用容斥原理来求满足题目要求的所有数字。(在求每一项的系数时可以利用莫比乌斯反演,但是弱弱不会,所以用了分解质因数的方法)。我们可以想到对于容斥原理中某一项的系数,奇数项系数为1,偶数项系数为-1,奇数项就对应质因子个数为奇数的,偶数项就对应质因子个数为偶数项的,然后我们对64以内的数字分解质因数,就可以求出每一项的系数。然后对于12,18这种项在容斥原理中是不包含的,我们也可以很轻易的把他们的系数定义为0。因此我们可以先预处理每一项的系数,然后对系数不为0的项二分求数字个数,然后求和即可。哦对,还有对1特判一下,如果L==1,那么结果++。二分的下界设为2即可。
AC代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 long long a[65],mp[65]; 6 long long qpow(long long x,int n){ 7 long long ans=1; 8 while(n){ 9 if(n&1){ 10 ans*=x; 11 } 12 x=x*x; 13 n/=2; 14 } 15 return ans; 16 } 17 void get(){ 18 mp[2]=1e9; 19 mp[3]=1e6; 20 mp[4]=31622; 21 mp[5]=3981; 22 mp[6]=1000; 23 mp[7]=372; 24 mp[8]=177; 25 mp[9]=100; 26 mp[10]=63; 27 mp[11]=43; 28 mp[12]=31; 29 mp[13]=24; 30 mp[14]=19; 31 mp[15]=15; 32 mp[16]=13; 33 mp[17]=11; 34 mp[18]=10; 35 mp[19]=8; 36 mp[20]=7; 37 mp[21]=7; 38 mp[22]=6; 39 mp[23]=6; 40 mp[24]=5; 41 mp[25]=5; 42 mp[26]=4; 43 mp[27]=4; 44 mp[28]=4; 45 mp[29]=4; 46 for(int i=30;i<=37;i++){ 47 mp[i]=3; 48 } 49 for(int i=38;i<=64;i++){ 50 mp[i]=2; 51 } 52 for(int i=2;i<=64;i++){ 53 int d=i; 54 int ans=0; 55 int q=0; 56 for(int j=2;j<=i;j++){ 57 int p=0; 58 while(d%j==0){ 59 d=d/j; 60 ans++; 61 p++; 62 } 63 if(p>1){q=1;break;} 64 } 65 if(q==1) a[i]=0; 66 else if(ans%2==1){ 67 a[i]=1; 68 } 69 else a[i]=-1; 70 } 71 } 72 long long judge(long long x,long long y,long long n){ 73 long long ans1=0,ans2=0; 74 long long low=2,high=mp[n]; 75 while(low<=high){ 76 long long mid=(low+high)/2; 77 if(qpow(mid,n)>=x){ 78 ans1=mid; 79 high=mid-1; 80 } 81 else { 82 low=mid+1; 83 } 84 } 85 low=2,high=mp[n]; 86 while(low<=high){ 87 long long mid=(low+high)/2; 88 if(qpow(mid,n)<=y){ 89 ans2=mid; 90 low=mid+1; 91 } 92 else { 93 high=mid-1; 94 } 95 } 96 if(ans2==0||ans1==0){ 97 return 0; 98 } 99 return ans2-ans1+1; 100 } 101 int main(){ 102 ios_base::sync_with_stdio(0); 103 cin.tie(0); 104 get(); 105 int q; 106 long long l,r; 107 while(cin>>q){ 108 long long result; 109 for(int i=1;i<=q;i++){ 110 cin>>l>>r; 111 result=0; 112 for(int j=2;j<=64;j++){ 113 if(a[j]!=0) result+=judge(l,r,j)*a[j]; 114 } 115 if(l==1) result++; 116 cout<<result<<endl; 117 } 118 } 119 return 0; 120 }