题意:
给你一个25位的N 要你找到一个a使得a⊗a=N
⊕的定义是无进位加法 即5+8=3
⊗的定义是 对于每一个乘倒这一位的数都用⊕来计算,即对于结果c来说,第k位
能想到的就是爆搜,虽然看起来是枚举每一位会有10次,但是真正匹配的我估计只有1,2个。那就枚举个位的情况,对于所有满足的爆搜。没有什么好讲的,没有啥技巧。首先答案的长度一定是(len+1)/2,对于len是偶数的情况,那么就是第一位是0,因为a*a的长度一定是奇数的,这个想一下就知道了。然后对于位数>(len+1)/2的情况,我就放到前面这些都确定了之后,最后检查是否可能时再算。
#include<bits/stdc++.h>
using namespace std;
const int N=30;
char s[N];
int a[N],n,len,ans[N];
int dfs(int now,int *ret){
if(now==len){
for(int i=len;i<n;i++){
int sum=0;
for(int j=len-1,k=i-j;k<len&&j>=1;k++,j--)
sum=(sum+ret[j]*ret[k])%10;
if(sum!=a[i])
return 0;
}
int f=0;
for(int i=len-1;~i;i--){
if(ret[i]<ans[i])
f=1;
else if(ret[i]>ans[i])
break;
}
if(f)
for(int i=0;i<len;i++)
ans[i]=ret[i];
return 1;
}
int sum=0,mul=2*ret[0];
for(int i=now-1,j=1;i;j++,i--)
sum=(sum+ret[i]*ret[j])%10;
int res=(a[now]-sum+10)%10;
int ans=0;
for(int i=0;i<=9;i++){
if(mul*i%10==res){
ret[now]=i;
if(dfs(now+1,ret))
ans=1;
}
}
return ans;
}
int main()
{
scanf("%s",s);
n=strlen(s);
if(n%2==0){
for(int i=n;~i;i--)
s[i+1]=s[i];
s[0]='0';
n++;
}
for(int i=0;i<n;i++)
a[i]=s[i]-'0';
for(int i=0;i<n/2;i++)
swap(a[i],a[n-i-1]);
len=(n+1)/2;
for(int i=0;i<=20;i++)
ans[i]=9;
int f=0;
int ret[13]={0};
for(int i=0;i<=9;i++){
if(i*i%10==a[0]){
ret[0]=i;
f=dfs(1,ret);
}
}
if(!f)
return 0*printf("-1\n");
for(int i=len-1;~i;i--)
printf("%d",ans[i]);
return 0;
}