https://ac.nowcoder.com/acm/contest/12606/C
题意:在不进位乘法下,给出n,求最小的满足a*a=n的正整数a
若n是偶数位则无解,因为若n的每一位编号位0-2*L,如果低位是0号,相乘,结果最低位是0号位,最高位是 2L*2L 号位,这一共是奇数个位
若n有L位,那么a有(L+1)/2位
因为要求最小正整数,所以要从高位到低位dfs
直接枚举a的每一位填什么
类似于列乘法竖式,a的每一位对n中的数位都有一个能产生影响的区间
每填一次就判断当前是否合法:
如果a的当前位不是最低位,就判断从n的最高位 到 a的低一位影响不到的位 是否合法
如果a的当前位是最低位,就判断所有位是否合法
#include<cstdio> #include<cstring> typedef long long LL; using namespace std; int lenn,lena; int a[60],n[60],b[60]; bool tag; //int c[10][5]={{1,0},{2,1,9},{0},{0},{2,2,8},{1,5},{2,4,6},{0},{0},{2,3,7}}; void dfs(int p) { int x; bool flag; if(!p) { for(int i=0;i<10;++i) { a[p]=i; flag=true; for(int j=lenn-1;j>=0 && flag;--j) { x=0; for(int k=0;k<=j;++k) x+=a[k]*a[j-k]; if(x%10!=n[j]) flag=false; } if(flag) { tag=true; for(int i=lena-1;i>=0;--i) printf("%d",a[i]); return; } } return; } int i=0; if(p==lena-1) i=1; for(i=0;i<10;++i) { a[p]=i; flag=true; for(int j=lenn-1;j>=p+lena-1 && flag;--j) { x=0; for(int k=0;k<=j;++k) x+=a[k]*a[j-k]; if(x%10!=n[j]) flag=false; } if(flag) { dfs(p-1); if(tag) return; } } } int main() { char s[28]; scanf("%s",s); if(s[0]==0) { printf("0"); return 0; } int l=strlen(s); for(int i=l-1;i>=0;--i) n[lenn++]=s[i]-'0'; lena=lenn+1>>1; dfs(lena-1); if(!tag) printf("-1"); }