本文主要是介绍FZU 2122,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Accept: 446 Submit: 2047 Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
Input
Output
Sample Input
Sample Output
Source
福州大学第十届程序设计竞赛
题目有个坑:long long 输出要用I64d
一元二次方程的求根公式:因为结果为正整数,所以x只能取(-i+sqrt(i*i+4*n)/2),i即为题目中的s(x,m)
得到这个通解,我们就可以直接枚举每一个i ,使得方程成立,并且由此得到的x可以通过m进制准换成i,
此题的技巧在于枚举的范围应该设为多大?
由题目可知数据最多取到10^18,也就是2^60左右,准换成16进制最多也就是16^15,所以s(x,m)的取值最多达到15*16(可能这个地方不太严谨,数学大佬可以尝试推一下,结果大致差不多就好了),所以我们枚举的范围设个两三百就够了
AC 代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<sstream>
#include<cctype>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI=acos(-1.0);
const double eps=1e-6;
const int INF=0x3f3f3f3f;
const int maxn=1234;int t;
int n,m;
int ans,flag;
int s(long long x,long long m)
{int ans=0;while(x){ans+=x%m;x/=m;}return ans;
}int main()
{int t;scanf("%d",&t);while(t--){long long n,m;scanf("%I64d %I64d",&n,&m);int flag=0;long long x;for(int i=1;i<=240;i++){x=((-i+sqrt(i*i+4*n))/2);if(x*x +s(x,m)*x-n==0&&s(x,m)==i){flag=1;break;}}if(flag)printf("%I64d\n",x);elseprintf("-1\n");}return 0;
}
这篇关于FZU 2122的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!