codeforces 955C Sad powers

题目链接: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代码:

  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 }
View Code
原文地址:https://www.cnblogs.com/ls961006/p/8670832.html