FZU-2125- 簡單的等式


E - 簡單的等式
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Submit

Status

Practice

FZU 2125
Description
現在有一個等式如下:x^2+s(x,m)x-n=0。其中s(x,m)表示把x寫成m進制時,每個位數相加的和。現在,在給定n,m的情況下,求出滿足等式的最小的正整數x。如果不存在,請輸出-1。
Input
有T組測試數據。以下有T(T<=100)行,每行代表一組測試數據。每個測試數據有n(1<=n<=10^18),m(2<=m<=16)。
Output
輸出T行,有1個數字,滿足等式的最小的正整數x。如果不存在,請輸出-1。
Sample Input
4
4 10
110 10
15 2
432 13
Sample Output
-1
10
3
18

考數學,考一元二次方程的求解。
s(x,m)的區間[1,100],只是粗略的估算,但不影響做題。
s(x,m)最小值為1,這個一眼就能看出來。接下來求它的最大值。
我只是粗略估算一下,2的100次方大於10的18次方。那2的100次方轉換為二進制時各個位數相加的和肯定小於100,那我就取右邊界為100.
為什么不轉換為16進制?因為這樣得到的返回值只會更小,不信自己拿筆算。

思路:不要枚舉x,枚舉s(x,m)。最多一百次,怎么會超時
原方程變為x*x+s(x,m)*x-n=0;s(x,m)看成可以被枚舉的已知數,那這就是關於x的一元二次方程了。經過配方開平方,可以得到
x=sqrt(n+(s(x,m)/2)*(s(x,m)/2))-s(x,m)/2;
通過配方得出x的值以后,帶入s(x,m),再帶入原方程檢驗即可。

代碼

#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<string>
#include<string.h>
using namespace std;
int s(long long int x,long long int m)
{
    int sum=0;
    while(x)
    {
        sum+=x%m;
        x=x/m;
    }
    return sum;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        long long int n,m;
        scanf("%I64d%I64d",&n,&m);
        long long int num_x=-1;//初始化
        for(int i=1;i<100;i++)//i代表s(x,m)參數
        {
            long long int flag=sqrt(n*4+i*i)/2-i/2;//求根公式得到
            if(flag*flag+s(flag,m)*flag==n)//帶入原方程檢驗
            {
                num_x=flag;
                break;
            }
        }
        printf("%I64d\n",num_x);
    }
}

注意數據類型


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com