给定
感觉差不多是绿题的难度,不卡精度的话应该算黄题难度,赛时的阴间思路在游记里了,这里说一下正解。
不难发现对于任意的合法的 unordered_set
里,最后直接输出其 size()
即可,考虑这样的复杂度,显然枚举
考虑对于 unordered_set
中的所有数,若其为完全平方数的话贡献
同时不难发现对于 double
的 sqrt()
函数的话会丢失精度,所以此时需考虑使用二分或 long double
或 __float128
,前者会多一个 __float128
会多一个十分巨大的甚至高于 sqrt()
然后取其返回值一段较小的邻域进行验证,一般
xxxxxxxxxx
721
2
3
4
5
6
7
8
9
10
11
12using namespace std;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23template < typename T = int >
24inline T read(void);
25
26ll N, K;
27unordered_set < ll > legal;
28ll ans(0);
29
30int main(){
31 auto qpow_with_lim = [](ll a, ll b)->ll{
32 ll ret(1), mul(a);
33 while(b){
34 if(b & 1)
35 ret = (__int128_t)ret * mul > N ? N + 1 : ret * mul;
36 b >>= 1;
37 mul = (__int128_t)mul * mul > N ? N + 1 : mul * mul;
38 }return ret;
39 };
40
41 N = read < ll >(), K = read();
42 if(K == 1)printf("%lld\n", N), exit(0);
43 legal.insert(1);
44 for(ll i = 2; i <= (ll)1e6; ++i){
45 auto cur = (__int128_t)qpow_with_lim(i, K == 2 ? 3 : K);
46 while(cur <= N)
47 legal.insert(cur), cur *= i;
48 }ans += legal.size();
49 if(K == 2){
50 for(auto v : legal)
51 if((ll)sqrt((ld)v) * (ll)sqrt((ld)v) == v)--ans;
52 ans += (ll)floor(sqrt((ld)N));
53 }printf("%lld\n", ans);
54 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
55 return 0;
56}
57
58template < typename T >
59inline T read(void){
60 T ret(0);
61 int flag(1);
62 char c = getchar();
63 while(c != '-' && !isdigit(c))c = getchar();
64 if(c == '-')flag = -1, c = getchar();
65 while(isdigit(c)){
66 ret *= 10;
67 ret += int(c - '0');
68 c = getchar();
69 }
70 ret *= flag;
71 return ret;
72}
update-2023_03_06 初稿