bzoj2432

被虐的体无完肤,

直接给题解地址吧:http://vfleaking.blog.163.com/blog/static/174807634201341721051604/

  1 const maxk=1000010;
  2 type matrix=array[1..3,1..3] of int64;
  3 var a:array[0..maxk*6] of longint;
  4     first,last,b,len:array[0..maxk] of longint;
  5     pre:array[0..maxk] of longint;
  6     n,k,p,x,y,sum:int64;
  7     i,j:longint;
  8     ans,aa,bb,s:matrix;
  9
 10 function ni(x:int64; y:longint):int64;
 11   begin
 12     ni:=1;
 13     while y>0 do
 14     begin
 15       if y mod 2=1 then ni:=ni*x mod k;
 16       y:=y div 2;
 17       x:=x*x mod k;
 18     end;
 19   end;
 20
 21 procedure work;
 22   var i,d,ph:longint;
 23   begin
 24     a[1]:=1;a[2]:=1;i:=2;
 25     while true do
 26     begin
 27       inc(i);
 28       a[i]:=(a[i-1]+a[i-2]) mod k;
 29       if first[a[i]]=0 then first[a[i]]:=i;
 30       if (a[i]=1) and (a[i-1]=1) then break;
 31     end;
 32     d:=k;
 33     ph:=k;
 34     for i:=2 to trunc(sqrt(k)) do
 35       if d mod i=0 then
 36       begin
 37         ph:=ph div i*(i-1);
 38         while d mod i=0 do d:=d div i;
 39       end;
 40     if d>1 then ph:=ph div d*(d-1);
 41
 42     for i:=1 to k-1 do
 43     begin
 44       pre[i]:=ni(i,ph-1);
 45       if int64(pre[i])*int64(i) mod k<>1 then pre[i]:=0;
 46     //  writeln(pre[i]);
 47     end;
 48     b[1]:=1;last[1]:=1;i:=1;
 49     while true do
 50     begin
 51       len[i]:=first[pre[b[i]]]-1;
 52       if len[i]<0 then break;
 53       inc(i);
 54       b[i]:=int64(a[len[i-1]])*b[i-1] mod k;
 55       if last[b[i]]>0 then break;
 56       last[b[i]]:=i;
 57     end;
 58     aa[1,2]:=1; aa[2,1]:=1; aa[2,2]:=1; aa[3,3]:=1;
 59     bb:=aa; bb[3,2]:=p-1;
 60   end;
 61
 62 operator *(a,b:matrix)c:matrix;
 63   var i,j,k:longint;
 64   begin
 65     for i:=1 to 3 do
 66       for j:=1 to 3 do
 67       begin
 68         c[i,j]:=0;
 69         for k:=1 to 3 do
 70           c[i,j]:=(c[i,j]+a[i,k]*b[k,j]) mod p;
 71       end;
 72   end;
 73
 74 function f(a:matrix;n:int64):matrix;
 75   begin
 76     fillchar(f,sizeof(f),0);
 77     f[1,1]:=1;f[2,2]:=1;f[3,3]:=1;
 78     while n>0 do
 79     begin
 80       if n and 1=1 then f:=f*a;
 81       a:=a*a;
 82       n:=n div 2;
 83     end;
 84   end;
 85
 86 begin
 87   readln(n,k,p);
 88   if n<3 then
 89   begin
 90     writeln(1);
 91     exit;
 92   end;
 93   work;
 94   ans[1,1]:=1; ans[2,2]:=1; ans[3,3]:=1;
 95   if n>len[1] then
 96   begin
 97     dec(n,len[1]+1);
 98     ans:=ans*f(aa,len[1]-2)*bb;
 99   end
100   else begin
101     ans:=ans*f(aa,n-2);
102     n:=0;
103   end;
104   i:=2;
105   while n>0 do
106   begin
107     if (pre[b[i]]=0) or (len[i]<0) then
108     begin
109       ans:=ans*f(aa,n);
110       n:=0;
111       break;
112     end;
113     if last[b[i]]<i then break;
114     if n>len[i] then
115     begin
116       dec(n,len[i]+1);
117       ans:=ans*f(aa,len[i])*bb;
118     end
119     else begin
120       ans:=ans*f(aa,n);
121       n:=0;
122     end;
123     inc(i);
124   end;
125   if n<>0 then
126   begin
127     j:=i;
128     sum:=0;
129     fillchar(s,sizeof(s),0);
130     s[1,1]:=1; s[2,2]:=1; s[3,3]:=1;
131     for i:=last[b[j]] to j-1 do
132     begin
133       inc(sum,len[i]+1);
134       s:=s*f(aa,len[i])*bb;
135     end;
136     ans:=ans*f(s,n div sum);
137     n:=n mod sum;
138     i:=last[b[j]];
139     while n>0 do
140     begin
141       if n>len[i] then
142       begin
143         ans:=ans*f(aa,len[i])*bb;
144         dec(n,len[i]+1);
145       end
146       else begin
147         ans:=ans*f(aa,n);
148         n:=0;
149       end;
150       inc(i);
151     end;
152   end;
153   writeln((ans[1,2]+ans[2,2]+ans[3,2]) mod p);
154 end.

时间: 2024-11-26 07:22:05

bzoj2432的相关文章

[BZOJ2432][Noi2011]兔农 矩阵乘法+exgcd

2432: [Noi2011]兔农 Time Limit: 10 Sec  Memory Limit: 256 MB Description 农夫栋栋近年收入不景气,正在他发愁如何能多赚点钱时,他听到隔壁的小朋友在讨论兔子繁殖的问题.问题是这样的:第一个月初有一对刚出生的小兔子,经过两个月长大后,这对兔子从第三个月开始,每个月初生一对小兔子.新出生的小兔子生长两个月后又能每个月生出一对小兔子.问第n个月有多少只兔子?聪明的你可能已经发现,第n个月的兔子数正好是第n个Fibonacci(斐波那契)

【bzoj2432】【NOI2011】兔农

题目描述 农夫栋栋近年收入不景气,正在他发愁如何能多赚点钱时,他听到隔壁的小 朋友在讨论兔子繁殖的问题. 问题是这样的:第一个月初有一对刚出生的小兔子,经过两个月长大后,这 对兔子从第三个月开始,每个月初生一对小兔子.新出生的小兔子生长两个月后 又能每个月生出一对小兔子.问第 n 个月有多少只兔子? 聪明的你可能已经发现,第 n 个月的兔子数正好是第 n 个 Fibonacci(斐波那 契)数.栋栋不懂什么是 Fibonacci 数,但他也发现了规律:第 i+2 个月的兔子数 等于第 i 个月的

挖坑#1——矩阵乘法

BZOJ1706: [usaco2007 Nov]relays 奶牛接力跑 BZOJ1898: [Zjoi2004]Swamp 沼泽鳄鱼 BZOJ2326: [HNOI2011]数学作业 BZOJ3204: [NOI2013] 矩阵游戏 BZOJ2875: [Noi2012]随机数生成器 BZOJ1009: [HNOI2008]GT考试 BZOJ3231: [Sdoi2008]递归数列 BZOJ1875: [SDOI2009]HH去散步 BZOJ2432: [Noi2011]兔农 BZOJ353