逆元
就说这种题怎么考场上没有人AC,原来有坑点- -
考虑
hi
和
hi+1
的关系:
有
hi+1≡hi∗26−26n∗si+si(mod p)
①
即
(1−26n)∗si≡hi+1−26∗hi(mod p)
②
即
si≡hi+1−26∗hi1−26n(mod p)
因为有解,且模数
p>26
,因此我们似乎可以一位一位地确定答案。
然而坑点来了,可能出现
1−26n|p
,此时它并没有逆元,解不唯一,将会表现出
a∼z
都合法的情况,就会挂掉。为什么?从②式可以看出并不是没逆元的锅,只是因为我们列出的式子只能说明在这个取值下
hi
和
hi+1
可以同时合法,而不能保证
hi
和其他的能同时合法。这样是对的当且仅当存在唯一解 (因为不可能有其他可行解)。而在这个坑点时没有唯一解。怎么办?
回到①式,发现满足
1−26n|p
时一定会出现:
hi+1≡hi∗26(mod p)
又因为保证有解,可知如果满足了
hi
,
hi+1
一定也满足,因此暴力地让
h0
满足即可。
#include<cstdio>
#define N 100005
using namespace std;
namespace runzhe2000
{
typedef long long ll;
int n, p, y[N];
int fpow(int a, int b)
{
int r = 1; a = (a%p+p)%p;
for(; b; b>>=1)
{
if(b&1)r=(ll)r*a%p;
a=(ll)a*a%p;
}
return r;
}
void main()
{
scanf("%d%d",&n,&p);
for(int i = 1; i <= n; i++) scanf("%d",&y[i]);
if(fpow(26,n) == 1)
{
int tmp = y[1];
for(int i = n; i; i--)
{
int c = tmp % 26;
y[i] = c;
tmp /= 26;
}
for(int i = 1; i <= n; i++) printf("%c",y[i]+'a');
}
else
{
int inv = fpow(fpow(26,n)-1, p - 2);
y[n+1] = y[1];
for(int i = 1; i <= n; i++)
{
int a = (ll) (y[i] * 26ll - y[i+1]) % p * inv % p;
if(a < 0) a += p;
printf("%c",a+'a');
}
}
}
}
int main()
{
runzhe2000::main();
}