Codevs P1982 加密算法
题目描述 Description
Rivest是密码学专家。近日他正在研究一种数列E={E[1],E[2],……,E[n]},
且E[1]=E[2]=p(p为一个质数),E[i]=E[i-2]*E[i-1] (若2<i<=n)。
例如{2,2,4,8,32,256,8192,……}就是p=2的数列。在此基础上他又设计了一种加密
算法,该算法可以通过一个密钥q (q<p)将一个正整数n加密成另外一个正整数d,计
算公式为:d=E[n] mod q。现在Rivest想对一组数据进行加密,但他对程序设计不太
感兴趣,请你帮助他设计一个数据加密程序。
输入描述 Input Description
读入m,p。其中m表示数据个数,p用来生成数列E。
以下有m行,每行有2个整数n,q。n为待加密数据,q为密钥。
规模:0<p,n<2^31;0<q<p;0<m<=5000。
输出描述 Output Description
将加密后的数据按顺序输出到文件a.out。
第i行输出第i个加密后的数据。
样例输入 Sample Input
2 7
4 5
4 6
样例输出 Sample Output
3
1
数据范围及提示 Data Size & Hint
分析
该题极度恶心,感觉在卡pascal,c++党开读入优化各种常数优化卡过去了。。。而P党悲催了,怎么都过不去。。。
首先,有题目中的E[i]:=E[i-1]*E[i-2] 再加上底数相等可以推知指数是Fibonacci数列的第n项,然后就可以通过矩阵乘法来加速转移。
然后由于指数仍旧很大,通过高次幂取模的降幂公式来将次方降到可以承受的地步,再快速幂即可完成该题,,,
pascal被卡。。。。。。。。。。( ˇˍˇ ),郁闷怎么也过不去。最好卡过去1个,还剩两个超时。。。
代码如下
{$inline on}
program encrypt;
type matrix=array[1..2,1..2] of qword;
var m,p,n,q,px,ans:qword;
i:longint;
euler:longint;
c,t,f:matrix;
function _euler(x:longint):longint;inline;
var ans,n:longint;
i:longint;
begin
ans:=x;
n:=x;
i:=2;
while i*i<=x do
begin
if x mod i=0
then
begin
ans:=(ans div i)*(i-1);
while x mod i=0 do
x:=x div i;
end;
i:=i+1;
end;
if x>1 then ans:=(ans div x)*(x-1);
exit(ans);
end;
function _matrix(a,b:matrix;n,m,k:longint):matrix;inline;
var i,j,p:longint;
begin
fillchar(c,sizeof(c),0);
for i:=1 to n do
for j:=1 to m do
for p:=1 to k do
begin
c[i,j]:=(c[i,j]+((a[i,p] mod euler)*(b[p,j] mod euler)) mod euler) mod euler;
end;
exit(c);
end;
function power(a:matrix;b:longint):matrix;inline;
var sum:matrix;
begin
sum:=a;
b:=b-1;
while b<>0 do
begin
if b and 1=1 then sum:=_matrix(sum,a,2,2,2);
b:=b>>1;
a:=_matrix(a,a,2,2,2);
end;
exit(sum);
end;
function power2(a,b:qword):qword;inline;
var sum:qword;
begin
sum:=1;
while b<>0 do
begin
if b and 1=1 then sum:=(sum*a) mod q;
b:=b>>1;
a:=((a mod q)*(a mod q))mod q;
end;
exit(sum);
end;
begin
readln(m,px);
for i:=1 to m do
begin
readln(n,q);
euler:=_euler(q);
f[1,1]:=1; f[1,2]:=1;
t[1,1]:=0; t[1,2]:=1;
t[2,1]:=1; t[2,2]:=1;
case n of
1:begin n:=f[1,1] end;
2:begin n:=f[1,2] end
else begin
t:=power(t,n-2);
f:=_matrix(f,t,1,2,2);
n:=f[1,2] mod euler;
end
end;
ans:=power2(px,n);
writeln(ans mod q);
end;
end.
—————————————————♪(^∇^*)我是分割线╮(╯▽╰)╭——————————————————————————
评测结果
测试点#a01.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#a02.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#a03.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#a04.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#a05.in 结果:AC 内存使用量: 256kB 时间使用量: 4ms
测试点#a06.in 结果:AC 内存使用量: 128kB 时间使用量: 7ms
测试点#a07.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#a08.in 结果:AC 内存使用量: 256kB 时间使用量: 16ms
测试点#a09.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#a1.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#a10.in 结果:AC 内存使用量: 256kB 时间使用量: 3ms
测试点#a11.in 结果:AC 内存使用量: 256kB 时间使用量: 61ms
测试点#a12.in 结果:AC 内存使用量: 256kB 时间使用量: 144ms
测试点#a13.in 结果:AC 内存使用量: 256kB 时间使用量: 294ms
测试点#a14.in 结果:AC 内存使用量: 256kB 时间使用量: 716ms
测试点#a15.in 结果:AC 内存使用量: 256kB 时间使用量: 1074ms
测试点#a16.in 结果:AC 内存使用量: 256kB 时间使用量: 1231ms
测试点#a17.in 结果:AC 内存使用量: 256kB 时间使用量: 1156ms
测试点#a18.in 结果:TLE 内存使用量: 236kB 时间使用量: 2000ms
测试点#a19.in 结果:TLE 内存使用量: 256kB 时间使用量: 2000ms
测试点#a2.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#a20.in 结果:AC 内存使用量: 364kB 时间使用量: 1917ms
测试点#a3.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
————————————————————————————————————————————————————————————————————————————————