题目背景
众所周知,一场考试需要一道签到题。
题目描述
给定 n , m,求有多少个正整数 x,使得 xm ≤ n。
输入格式
一行两个正整数 n , m。
输出格式
一个整数表示正整数 x 的个数。
输入输出样例
输入 #1
5 2
输出 #1
2
说明/提示
对于 25\%25% 的数据满足 m = 1。
对于 50\%50% 的数据满足 n ≤ 106。
对于100\%100%的数据满足 n , m ≤ 109。
这是昨天洛谷月赛Div.2的T1
确实非常签到(但就是花了好大功夫才做出来,淦)
看到题目首先联想到的是快速幂
很快就否定了这种解法(其实我根本没想用快速幂)
看到这个 xm ≤ n又准备用cmath库的log函数做个换底来减少枚举量
但是花了将近四十五分钟以后以失败告终(谁知道这是个纯暴力呢)
于是准备打个m == 1 的表(前25%)然后暴力枚举
于是有了以下代码
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <algorithm> #include <cstdlib> #include <set> using namespace std; long long n, m; long long x; long long cnt = 0; inline long long read() { long long x = 0; long long w = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 3) + (x << 1) + c - '0'; c = getchar(); } return x * w * 1ll; } int main() { n = read(); m = read(); if(m == 1) printf("%lld", n); if(m > n) printf("1"); if(m == 2) { for(int i = 1; i <= sqrt(n) ; i++) { if(pow(i , 2) <= n) cnt++; } cout<<cnt; } if(m == 4) { for(int i = 1; i <= (sqrt(n)); i++) { if(pow(i , m) <= n) cnt++; } cout<<cnt; } if(m != 2 && m != 4){ for(int i = 1; i <= sqrt(n); i++) { if(pow(i , m) <= n) cnt++; cout<<cnt; } } /* double ans; // log(n)/m == log(x); double need = log(n) / m; for(int i = 1; i <= 1e6; i++) { ans = log(i); if(ans == need) { cout<<i; return 0; } } cout<<"No answer"; */ }
结果它就SPFA了...
我们来想想为啥
是数组开小了么——会RE
是递归次数不够么——扯
好像是这一段不大对
if(m > n)
printf("1");
于是在一脸懵逼中我把代码改成了下面这样
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <algorithm> #include <cstdlib> #include <set> using namespace std; long long n, m; long long x; long long cnt = 0; inline long long read() { long long x = 0; long long w = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 3) + (x << 1) + c - '0'; c = getchar(); } return x * w * 1ll; } int main() { n = read(); m = read(); if(m == 1) printf("%lld", n - 1); if(m == 2) { for(int i = 1; i <= sqrt(n) ; i++) { if(pow(i , 2) <= n) cnt++; } cout<<cnt; } if(m == 4) { for(int i = 1; i <= (sqrt(n)); i++) { if(pow(i , m) <= n) cnt++; } cout<<cnt; } if(m != 2 && m != 4) { for(int i = 1; i <= sqrt(sqrt(n)); i++) { if(pow(i , m) <= n) cnt++; } cout<<cnt; } /* double ans; // log(n)/m == log(x); double need = log(n) / m; for(int i = 1; i <= 1e6; i++) { ans = log(i); if(ans == need) { cout<<i; return 0; } } cout<<"No answer"; */ }
用导数的思想对递归进行一些优化
于是我又交了一遍...
?
我直接疑天下之大惑
为啥会WA一个点?
???
于是开始一点点地排查
最后发现...
if(m == 1) printf("%lld", n);
就不该写,导致跟后面(m != 2 && m != 4)判重了...
本来想骗的25居然没拿到...
淦
改成这样就行辣(我也不知道109数据枚举咋过去的反正我就是过去了)
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <algorithm> #include <cstdlib> #include <set> using namespace std; long long n, m; long long x; long long cnt = 0; inline long long read() { long long x = 0; long long w = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 3) + (x << 1) + c - '0'; c = getchar(); } return x * w * 1ll; } int main() { n = read(); m = read(); if(m == 1) printf("%d", n); if(m == 2) { for(int i = 1; i <= sqrt(n) ; i++) { if(pow(i , 2) <= n) cnt++; } cout<<cnt; } if(m == 4) { for(int i = 1; i <= (sqrt(n)); i++) { if(pow(i , m) <= n) cnt++; } cout<<cnt; } if(m != 2 && m != 4 && m != 1) { for(int i = 1; i <= sqrt(sqrt(n)); i++) { if(pow(i , m) <= n) cnt++; } cout<<cnt; } /* double ans; // log(n)/m == log(x); double need = log(n) / m; for(int i = 1; i <= 1e6; i++) { ans = log(i); if(ans == need) { cout<<i; return 0; } } cout<<"No answer"; */ }