题意
求[l,r]的最大指数和(1<=l,r<=10^18)
最大指数和(如64=8^2=4^3=2^6,所以64的最大指数和是6)
题解
很明显我们可以先求出[1,n]的最大指数和,然后再作差。
我们可以先求出num[i]代表[1,n]中最大指数为i的数有多少个。
然后枚举全部的i,然后让答案加上i*num[i];
那么怎么求num[i]呢
我们可以求出[1,n]中指数为x的数有多少个作为num[x]的初步值。这个用n1/x就可以求出(不过要注意精度问题,及其恶心,看代码吧)
然后这个num却对是不对的。我们发现16=4^2=2^4,num[2]中却有16,所以我们用num[2]-num[4]就行了。
我们发现对于每一对i>j且i%j==0num[j]都需要减num[i],不过我们要倒序枚举j。
具体看代码吧。
1 #include<iostream> 2 #include<cmath> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cstring> 6 using namespace std; 7 const long long INF=1e18+1; 8 const long long inf=(long long)1<<31; 9 long long dp[100],a,b,n; 10 long long ksm(long long x,long long b){ 11 long long tmp=1; 12 while(b){ 13 if(b&1){ 14 double num=1.0*INF/tmp; 15 if(x>num)return -1; 16 tmp=tmp*x; 17 } 18 b>>=1; 19 if(x>inf&&b>0)return -1; 20 x=x*x; 21 } 22 return tmp; 23 } 24 long long calc(long long n,long long x){ 25 long long a=(long long)(pow((double)(n),1.0/x)+1e-9); 26 long long b=ksm(a,x); 27 if(b==n)return a; 28 if(b==-1||b>n)return a-1; 29 long long c=ksm(a+1,x); 30 if(c!=-1&&c<=n)return a+1; 31 else return a; 32 } 33 long long solve(long long x){ 34 if(x==0)return 0; 35 if(x==1)return 1; 36 long long k; 37 dp[1]=x; 38 for(long long i=2;i<=62;i++){ 39 dp[i]=calc(x,i)-1; 40 if(dp[i]==0){ 41 k=i-1; 42 break; 43 } 44 } 45 for(long long i=k;i>=1;i--) 46 for(long long j=1;j<i;j++){ 47 if(i%j==0)dp[j]-=dp[i]; 48 } 49 long long ans=dp[1]; 50 for(long long i=2;i<=k;i++){ 51 ans+=dp[i]*i; 52 } 53 return ans; 54 } 55 int main(){ 56 while(scanf("%lld%lld",&a,&b)!=EOF){ 57 if(a==0&&b==0)break; 58 printf("%lld ",solve(b)-solve(a-1)); 59 } 60 return 0; 61 }