題目鏈接
題意:給你一個素數P(P<=30000)和一串長爲n的字符串str[]。字母’*’代表0,字母a-z分別代表1-26,這n個字符所代表的數字分別代表f(1)、f(2)….f(n)。
定義f(k) = ∑(0<=i<=n-1)ai*k^i(mod p)
通過定義可以列出n個方程
f(1) = a0 * 1^0 + a1 * 1^1 + a2 * 1^2 ,,,,,,,a(n-1) * 1^n
f(2) = a0 * 1^0 + a1 * 2^1 + a2 * 2^2 ,,,,,,,a(n-1) * 2^n
f(3) = a0 * 3^0 + a1 * 3^1 + a2 * 3^2 ,,,,,,,a(n-1) * 3^n
,,,
,,,
f(n) = a0 * n^0 + a1 * n^1 + a2 * n^2 ,,,,,,,a(n-1) * n^n
然後用高斯消元求解就行了,題目已說明有唯一解
代碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <math.h>
#include <vector>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=105;
ll mat[maxn][maxn];
ll p;
char str[105];
ll x[maxn];
bool free_x[maxn] ;
int guass(int n,int m){//n行m列
memset (x,0,sizeof (x));//把解集清空,所有變量都標爲自由變量?
memset (free_x,true,sizeof (free_x));
int k,col;
for (k=0,col=0;k<n&&col<m;k++,col++){//枚舉行列
int max_r=k;//找到該col列元素絕對值最大的那行與第k行交換.(爲了在除法時減小誤差)
for (int i=k+1;i<n;i++){
if (fabs(mat[i][col])>fabs(mat[max_r][col]))max_r=i;
}
if (max_r!=k){//變換
for (int i=k;i<m+1;i++)swap(mat[k][i],mat[max_r][i]);
}
for (int i=k+1;i<n;i++)if (mat[i][col]!=0){
ll x1=mat[i][col],x2=mat[k][col];
for (int j=col;j<m+1;j++){
mat[i][j]=mat[i][j]*x2-x1*mat[k][j];
mat[i][j]=(mat[i][j]%p+p)%p;
}
}
}
for (int i=k-1;i>=0;i--){
ll tmp=mat[i][m];
for (int j=i+1;j<m;j++){
tmp=((tmp-mat[i][j]*x[j])%p+p)%p;
}
while (tmp%mat[i][i])tmp+=p;
x[i]=((tmp/mat[i][i])%p+p)%p;
}
return 0;
}
int n;
int main()
{
int T;
scanf ("%d",&T);
while (T--){
scanf ("%lld",&p);
scanf ("%s",str);
memset (mat,0,sizeof (mat));
int len=strlen(str);
for (int i=0;i<len;i++){
if (str[i]!='*')mat[i][len]=str[i]-'a'+1;
mat[i][0]=1;
for (int j=1;j<len;j++){
mat[i][j]=(mat[i][j-1]*(i+1))%p;
}
}
guass(len,len);
for(int i=0;i<len;i++){
if (!i)printf ("%d",x[i]);
else printf (" %d",x[i]);
}
printf ("\n");
}
return 0;
}