FZU 2125 简单的等式

Posted 小小八

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FZU 2125 简单的等式相关的知识,希望对你有一定的参考价值。

题目链接:简单的等式

比赛的时候感觉没有思路,大腿说可能是枚举想一下有什么限制好了。然后莫名想出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\n", ans);
    }
    return 0;
}

对于这道题,从没有思路到想出S(x, m)限制,到代码实现都值得思考呢......

以上是关于FZU 2125 简单的等式的主要内容,如果未能解决你的问题,请参考以下文章

FZU - 2204 简单环形dp

bzoj2125 最短路——仙人掌两点间距离

fzu 2039 Pets (简单二分图 + (最大流 || 二分图))

LeetCode 2125. 银行中的激光束数量

简单的布尔不等式运算符错误

BZOJ 2125: 最短路