HDU Integer's Power(容斥原理)

题意

求[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\n",solve(b)-solve(a-1));
59     } 
60     return 0;
61 }

 

posted @ 2018-09-27 20:28  Xu-daxia  阅读(229)  评论(0编辑  收藏  举报