题目链接:简单的等式
比赛的时候感觉没有思路,大腿说可能是枚举想一下有什么限制好了。然后莫名想出S(x, m)是有一个范围的,然后告知大腿,大腿敲之,WA之,发现maxn应该是10^18,num[i]的最大还是应该是10^9的。【据大腿说改成10^18就过了,然刚试了下,10^9即可。】
赛后重敲的时候,num数组想错了,比如说,10^10用m进制表示时,位数之和最大应该是9*9+1。然我算成10了。
还有个坑点在哪呢.....输入的时候n需要用long long表示 如果是%ll 就WA,如果是%I64d就AC,当然cin 大法也没有问题.....【遇见两次了,不解】
无脑的逐行排除才发现...以后再也不这样dbug了....T_T
附AC代码:
/* 思路:对于给定的m,S(x, m) 的范围可以确定最大值。 S(x, m) = n / x - x,函数递减,所以遍历x的时候,从sqrt(n) 遍历到S(X, m)递增到最大值过程中得到的满足条件的x的最小值即为ans. */ #include <stdio.h> #include <string.h> #include <iostream> #include <cmath> #define maxn 1e9 using namespace std; long long num[20]; void init() { // 计算maxn表示成进制时,各位之和相加的最大值 for (int i=2; i<=16; ++i) { long long st = 1; int ans = 0; while(st <= maxn) { st *= i; ans += i-1; } num[i] = ans-i+1; } } int get(long long x, int m) { // 计算x写成m进制各位相加之和 long long st = x; int ans = 0; while(st) { ans += st % m; st /= m; } return ans; } int main() { init(); int t; scanf("%d", &t); while(t--) { long long n; int m; scanf("%I64d%d", &n, &m); long long st = (long long)sqrt(n); long long ans = -1; for (long long i=st; i>0; --i) { if (n / i - i > num[m]) break; if (n%i != 0) continue; if (n / i - i == get(i, m)) { ans = i; } } printf("%lld ", ans); } return 0; }
对于这道题,从没有思路到想出S(x, m)限制,到代码实现都值得思考呢......