题目大意:已知N,求满足等式M2%10x=N (x=0,1,2,3....)中的M。
解题思路:仔细读题可以发现就是求N是否为M2中的子串,直接进行BFS就可以,但是由于要求最小的,则利用优先队列来存储该值,数据量为10^9,要用longlong来接收。只需要从低位向高位开始搜索,每一位分别进行判断,如果该位的N与M^2相等,则满足条件,压入队列。记录M时要将低位满足条件的数进行记录进入下一位的判断。每次获取队首元素,判断是否满足等式即可。详见code。
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=4394
http://www.acm.uestc.edu.cn/#/problem/show/850
code:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
typedef long long ll;
ll n,ans;
int T;
struct node{
ll m;
int x;
bool operator < (const node &p) const{
return p.m<m;
}
};
bool BFS(){
node s,t,e;
priority_queue<node> q;
s.m=0;s.x=0;
q.push(s);
while(!q.empty()){
t=q.top();
q.pop();
ll tmp=(ll)pow(10,t.x);
if(t.m*t.m%tmp==n){ //满足条件输出
ans=t.m;
return true;
}
for(int i=0;i<=9;i++){ //进行
e.x=t.x+1; //记录x
e.m=t.m+i*tmp; //记录m,其中t.m为压入队列中满足低位条件的数,i*tmp为本位的数,需要进行遍历判断
if(e.m*e.m%(tmp*10)==n%(tmp*10)) //如果该位存在n与m^2相等,则压入队列
q.push(e);
}
}
return false;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%I64d",&n);
if(BFS()) printf("%I64d\n",ans);
else printf("None\n");
}
return 0;
}
UESTC上的评判系统不一样,HDU过了,在CDOJ上老是PE,后边才发现是输出的问题,longlong型的我开始用了%I64d输出,应该用%lld,晕死,,,再做了一下剪枝,详见code。
CDOJcode:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
typedef long long ll;
ll n,ans;
int T;
struct node{
ll m;
int x;
bool operator < (const node &p) const{
return p.m<m;
}
};
bool BFS(){
node s,t,e;
priority_queue<node> q;
s.m=0;s.x=0;
q.push(s);
while(!q.empty()){
t=q.top();
q.pop();
ll tmp=(ll)pow(10,t.x);
if(t.m*t.m%tmp==n){
ans=t.m;
return true;
}
for(int i=0;i<=9;i++){
e.x=t.x+1;
e.m=t.m+i*tmp;
if(e.m*e.m%(tmp*10)==n%(tmp*10))
q.push(e);
}
}
return false;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%I64d",&n);
ll num=n%10;
if(num==2 || num==3 || num==7 || num==8)//剪枝,m的平方在低位不会出现2,3,7,8。
printf("None\n");
else{
if(BFS()) printf("%lld\n",ans); //注意输出类型
else printf("None\n");
}
}
return 0;
}