题目:http://acm.hdu.edu.cn/showproblem.php?pid=5297
1.看完题有一个大概思路:二分加容斥,容斥的话62以内大约有15个左右的质数,每次容斥如果2^15左肯定超时,但是可以发现很多状态其实不用考虑,比如x^91在long long范围内根本不用考虑。可以先预处理一下,最多需要考虑大约40个状态。这样写了二分交了居然T了。。。
2.一下子搞不清楚能不能用莫比乌斯反演,需要复习一下莫比乌斯反演的使用条件
3.试了下减小二分的范围,T
4.最后查了题解,是迭代的。如果说当前检验的这个数num是第m个合法数字的话,那么第n个合法数字一定>= num + n - m
5.复杂度玄学。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cmath>
#include <vector>
#include <sstream>
#include <bitset>
#include <deque>
#include <iomanip>
using namespace std;
#define pr(x) cout << #x << " = " << x << endl;
#define bug cout << "bugbug" << endl;
#define ppr(x, y) printf("(%d, %d)\n", x, y);
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define SQR(a) ((a)*(a))
#define PCUT puts("\n---------------")
typedef long long ll;
typedef double DBL;
typedef pair<int, int> P;
typedef unsigned int uint;
const int MOD = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 1e2 + 4;
const int maxm = 1e3 + 4;
const double pi = acos(-1.0);
const double eps = 1e-12;
int a[maxn] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 83, 89}, r;
int tmp[maxn];
ll n, num;
vector<P> v;
vector<int> w;
inline ll compute(int m, ll maxv){
int num = pow(maxv+0.5, 1.0/m);
return num - 1;
}
ll fun(ll num, int r){
ll record = num;
num--;
// pr(r);
// cout << "once " << endl;
for (int i = 0; i < v.size(); ++i){
if (v[i].second > r) break;
// if (v[i].first == 3){
// ppr(v[i].first, record);
// cout << int(compute(v[i].first, record)) * w[i] << endl;
// cout << compute(3, 1331) << endl;
// }
num += compute(v[i].first, record) * w[i];
// cout << num << endl;
}
// system("pause");
return num;
}
ll binary(ll n, int r){
/* ll lft = n, rght = n+2e9;
while(lft < rght){
ll mid = (lft + rght) / 2;
if (fun(mid, tmp[r]) >= n) rght = mid;
else lft = mid + 1;
}
*/
ll lft = n, T;
while((T = fun(lft, tmp[r])) < n){
lft += n - T;
}
return lft;
}
int main(){
//必须编译过才能交
int ik, i, j, k, kase;
// freopen("input.txt", "r" , stdin);
// freopen("output.txt", "w", stdout);
for (i = 1; i < (1 << 18); ++i){
int base = 1;
bool flag = true;
for (j = 0; j < 18; ++j)
if (i >> j & 1){
base *= a[j];
if (base > 62) flag = false;
}
if (flag){
v.push_back({base, i});
w.push_back((__builtin_popcount(i) & 1) ? -1 : 1);
}
}
// cout << ll(2e18) << endl;
// cout << pow(1331, 1.0/3) << endl;
// cout << pow(1331, 1.0/5) << endl;
// cout << pow(1331, 1.0/7) << endl;
for (i = 2; i < 63; ++i){
tmp[i] = lower_bound(a, a+18, i) - a;
if (a[tmp[i]] != i) tmp[i]--;
tmp[i]++;
tmp[i] = (1 << tmp[i]) - 1;
}
scanf("%d", &kase);
while(kase--){
scanf("%I64d %d", &n, &r);
printf("%I64d\n", binary(n, r));
// printf("%d\n", n);
}
return 0;
}
/*
100
1285 10
*/