给定
感觉差不多是绿题的难度,不卡精度的话应该算黄题难度,赛时的阴间思路在游记里了,这里说一下正解。
不难发现对于任意的合法的 unordered_set 里,最后直接输出其 size() 即可,考虑这样的复杂度,显然枚举
考虑对于 unordered_set 中的所有数,若其为完全平方数的话贡献
同时不难发现对于 double 的 sqrt() 函数的话会丢失精度,所以此时需考虑使用二分或 long double 或 __float128,前者会多一个 __float128 会多一个十分巨大的甚至高于 sqrt() 然后取其返回值一段较小的邻域进行验证,一般
xxxxxxxxxx72123
4567891011
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 初稿