题目地址:POJ 2065
题意:输入一个素数p和一个字符串s(只包含小写字母和‘*’),字符串中每个字符对应一个数字,'*'对应0,‘a’对应1,‘b’对应2....
eg:str[] = "abc", 那么说明 n=3, 字符串所对应的数列为1, 2, 3。
同时题目定义了一个函数:a0*1^0 + a1*1^1+a2*1^2+........+an-1*1^(n-1) = f(1)(mod p), f(1) = str[0] = a = 1;
a0*2^0 + a1*2^1+a2*2^2+........+an-1*2^(n-1) = f(2)(mod p), f(2) = str[1] = b = 2;
..........
a0*n^0 + a1*n^1+a2*n^2+........+an-1*n^(n-1) = f(n)(mod p),f(n) = str[n-1] = ````
求出 a0,a1,a2....an-1。
思路:和POJ 2947很相像,只不过这道题的解是唯一确定的,也就是不需要判断无解和无穷解的情况,同时求i^(n-1)的时候用快速幂取余做,pow会溢出。
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <set>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const double pi= acos(-1.0);
const double esp=1e-6;
const int MAXN=110;
int aug[MAXN][MAXN];
int x[MAXN];
int m,n;
int gcd(int a,int b)
{
int r;
while(b!=0){
r=b;
b=a%b;
a=r;
}
return a;
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
int Gauss(int mod)
{
int i,j;
int LCM;
int ta,tb;
int row,col,max_r;
int tmp;
for(row=0,col=0;row<m&&col<n;row++,col++){
max_r=row;
for(i=row+1;i<m;i++){
if(abs(aug[i][col])>abs(aug[max_r][col]))
max_r=i;
}
if(max_r!=row){
for(j=row;j<n+1;j++)
swap(aug[row][j],aug[max_r][j]);
}
if(aug[row][col]==0){
row--;
continue;
}
for(i=row+1;i<m;i++){
if(aug[i][col]!=0){
LCM=lcm(aug[i][col],aug[row][col]);
ta=LCM/abs(aug[i][col]);
tb=LCM/abs(aug[row][col]);
if(aug[i][col]*aug[row][col]<0) tb=-tb;
for(j=col;j<n+1;j++){
aug[i][j]=((aug[i][j]*ta-aug[row][j]*tb)%mod+mod)%mod;
}
}
}
}
for(i=n-1;i>=0;i--){
tmp=aug[i][n];
for(j=i+1;j<n;j++){
if(aug[i][j]!=0)
tmp-=aug[i][j]*x[j];
tmp=(tmp%mod+mod)%mod;
}
while(tmp%aug[i][i]!=0)
tmp+=mod;
x[i]=(tmp/aug[i][i])%mod;
}
return 0;
}
int pow_mod(int a,int n,int mod)
{
int ans=1;
while(n){
if(n&1)
ans=(ans*a)%mod;
a=(a*a)%mod;
n>>=1;
}
return ans;
}
int main()
{
int T,p,i,j;
char str[MAXN];
scanf("%d",&T);
while(T--){
scanf("%d %s",&p,str);
n=m=0;
int len=strlen(str);
for(i=0;i<len;i++){
if(str[i]=='*')
aug[i][len]=0;
else
aug[i][len]=str[i]-'a'+1;
for(j=0;j<len;j++)
aug[i][j]=pow_mod(i+1,j,p);
}
n=m=len;
Gauss(p);
for(i=0;i<len-1;i++)
printf("%d ",x[i]);
printf("%d\n",x[i]);
}
return 0;
}