[NOI 2012]乱数生成器[CodeVS 1281]Xn数列
7108 ワード
テーマ説明Description
6個の数をあげますm,a,c,x 0,n,g
Xn+1=(aXn+c)mod m、Xnを求めます
m, a, c, x0, n, g<=10^18
入力記述Input Description
1行6個数m,a,c,x 0,n,g
出力記述Output Description
出力数Xn mod g
サンプル入力Sample Input
11 8 7 1 5 3
サンプル出力Sample Output
2
問題解 [xnc]=[xn−1c]⋅[a101] 直接行列乗算にかかわらずQQQQ が爆発するだから高速べき乗を真似て高速加算(a*b=a+a+a+.....+a) を書くもっと速くしたいなら、その2 X 2の行列の2列目は変わらないことに気づきます.
6個の数をあげますm,a,c,x 0,n,g
Xn+1=(aXn+c)mod m、Xnを求めます
m, a, c, x0, n, g<=10^18
入力記述Input Description
1行6個数m,a,c,x 0,n,g
出力記述Output Description
出力数Xn mod g
サンプル入力Sample Input
11 8 7 1 5 3
サンプル出力Sample Output
2
問題解
var
m,a,c,x0,n,s,ans:int64;
d,e,f,g:qword;
t,y:array[1..2,1..2]of qword;
i,j,k:longint;
function mmod(a,b:int64):qword;
var len:int64;
begin
len:=0;
while b<>0 do
begin
if (b and 1)=1
then len:=(len+a)mod m;
a:=(a*2)mod m;
b:=b div 2;
end;
exit(len);
end;
begin
readln(m,a,c,x0,n,s);
t[1,1]:=1; t[1,2]:=0; t[2,1]:=0; t[2,2]:=1;
y[1,1]:=a; y[1,2]:=0; y[2,1]:=1; y[2,2]:=1;
while n<>0 do
begin
if (n and 1)=1
then begin {t=t*y}
d:=(mmod(t[1,1],y[1,1])+mmod(t[1,2],y[2,1]))mod m;
e:=(mmod(t[1,1],y[1,2])+mmod(t[1,2],y[2,2]))mod m;
f:=(mmod(t[2,1],y[1,1])+mmod(t[2,2],y[2,1]))mod m;
g:=(mmod(t[2,1],y[1,2])+mmod(t[2,2],y[2,2]))mod m;
t[1,1]:=d; t[1,2]:=e; t[2,1]:=f; t[2,2]:=g;
end;
{y=y*y}
d:=(mmod(y[1,1],y[1,1])+mmod(y[1,2],y[2,1]))mod m;
e:=(mmod(y[1,1],y[1,2])+mmod(y[1,2],y[2,2]))mod m;
f:=(mmod(y[2,1],y[1,1])+mmod(y[2,2],y[2,1]))mod m;
g:=(mmod(y[2,1],y[1,2])+mmod(y[2,2],y[2,2]))mod m;
y[1,1]:=d; y[1,2]:=e; y[2,1]:=f; y[2,2]:=g;
n:=n div 2;
end;
ans:=(((mmod(x0,t[1,1])+mmod(c,t[2,1])+m)mod m)+s)mod s;
writeln(ans);
end.