题目链接:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2165
Crack Mathmen
题目意思:给你一串数,加密,让你还原,如果不能还原或者有多个结果,则输出:“No Solution”。这题可以用快速幂做,也可以找循环节打表,时间居然是一样的。。。而且要注意的地方就是不是只有字母,还有其他字符,我就是被坑在这个地方。。。
快速幂:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int mod=997;
char a[1000];
int fun(int x,int b)
{
int r=1;
while(b)
{
if(b&1)
r=(r*x)%mod;
x=(x*x)%mod;
b>>=1;
}
return r;
}
int init(int n)
{
memset(a,0,sizeof(a));
int i;
for(i=32;i<=126;i++) //不一定只有字母,还有可能有其他字符
{
int t=fun(i,n);
if(a[t]==0)
a[t]=char(i);
else
return 0;
}
return 1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int i,l,flag=1,sum;
string str,ans="";
int n;
cin>>n>>str;
l=str.size();
if(init(n))
{
for(i=0;i<l;i+=3)
{
sum=((str[i]-'0')*100+(str[i+1]-'0')*10+str[i+2]-'0');
if(a[sum]!=0)
ans+=a[sum];
else
{
flag=0;
break;
}
}
}
else
flag=0;
if(n==0)
flag=0;
if(flag)
cout<<ans<<endl;
else
printf("No Solution\n");
}
return 0;
}
打表:
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
const int mod=997;
int a[1000][130],tmp[130];
int main()
{
int i,j;
for(i=32;i<=126;i++)
{
a[0][i]=1;
a[1][i]=tmp[i]=i;
}
for(i=1;i<=996;i++) //循环节为996
{
for(j=32;j<=126;j++)
a[i][j]=(a[i-1][j]*tmp[j])%mod;
}
int T;
scanf("%d",&T);
while(T--)
{
int i,l,n,sum,flag=0;
char c;
string str,ans="";
scanf("%d",&n);
cin>>str;
n%=996;
if(n==0)
{
printf("No Solution\n");
continue;
}
for(i=32;i<=126;i++)
{
for(j=i+1;j<=126;j++)
{
if(a[n][i]==a[n][j])
{
flag=1;
printf("No Solution\n");
break;
}
}
if(flag)
break;
}
if(flag)
continue;
l=str.size();
for(i=0;i<l;)
{
sum=0,flag=0;
for(j=0;j<3;i++,j++)
sum=sum*10+str[i]-'0';
for(j=32;j<=126;j++)
if(sum==a[n][j])
{
flag=1;
ans+=char(j);
//cout<<ans<<endl;
break;
}
if(!flag)
break;
}
if(!flag)
printf("No Solution\n");
else
cout<<ans<<endl;
}
return 0;
}