标签:
传送门:点击打开链接
很明显会有大量重复的被计算,所以很容易就想到容斥定理。
我们设dp[i]表示能表示成M^i(i>1)且i是这个数字能表示出来的最大的情况时的总类数
比如,27拆成M^K时的K最大能表示成3,所以27这个数字分在dp[3]这一类
1我们暂时不考虑,不把它放在任何一类
因为K>1,所以K至少是2,最大是2^K=N的时候,所以K最大等于log2(N),所以K非常的小
首先,求出K最大大概的位置
然后开始求dp[i]。求法如下:
首先,1~N中有哪些是能拆分成M^i的,利用pow函数可以算出来,暂时记为dp[i]
按照dp[i]的要求,还必须要排除K目前不是表示最大的情况,相当于容斥了,如下
dp[i]=dp[i]-dp[2*i]-dp[3*i]-dp[4*i]-.......
这样处理完后,dp[i]就是能表示成M^i(i>1)且i是这个数字能表示出来的最大的情况时的总类数了
最后的答案就是dp[2]+dp[3]+....+dp[K的最大值],再加上我们之前没考虑的1就可以了
#include<map> #include<set> #include<cmath> #include<stack> #include<queue> #include<cctype> #include<cstdio> #include<string> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; typedef pair<int, int> PII; const int MX = 1e3 + 5; const double exps = 1e-8; LL dp[MX]; int main() { LL n;//FIN; while(~scanf("%I64d", &n)) { memset(dp, 0, sizeof(dp)); int p = ceil(log2(1.0 * n)) + 1; LL ans = 1; for(int i = p; i >= 2; i--) { dp[i] = pow(1.0 * n, 1.0 / i) - 1 + exps; for(int j = 2 * i; j <= p; j += i) { dp[i] -= dp[j]; } ans += dp[i]; } printf("%I64d\n", ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/qwb492859377/article/details/47759471