LOJ10196越狱

题目描述

原题来自:HNOI 2008

监狱有连续编号为 1 到 n 的 n 个房间,每个房间关押一个犯人。有 m 种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人信仰的宗教相同,就可能发生越狱。求有多少种状态可能发生越狱。

输入格式

输入两个整数 m 和n 

输出格式

可能越狱的状态数,对 100003 取余。

样例

样例输入

2 3

样例输出

6

样例说明

所有可能的 6 种状态为:

{0,0,0}{0,0,1}{0,1,1}{1,0,0}{1,1,0}{1,1,1}。

数据范围与提示

对于全部数据,1<=m<=1e8,1<=n<=1e12

______________________________________________

动态规划,f[i]表示到第i个房间越狱的情况有多少种。

则:f[i]=f[i-1]*m+(m^(i-1)-f[i-1])=m^(i-1)+(m-1)f[i-1]

f[i-1]*m表示前i-1个房间已经出现越狱情况,则第i个房间随便放一个宗教的犯人都会出现越狱

(m^(i-1)-f[i-1])表示前i-1个房间没有出现越狱的情况等于所有的情况减去有越狱的情况。

数据太大,需要矩阵快速幂。

[ 0 , 1 ]          [m-1,0 ]

                     [m   ,m ]

______________________________________________

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll mod=100003;
 5 ll n,m;
 6 struct jz22
 7 {
 8     ll jz[2][2];
 9     jz22()
10     {
11         jz[1][0]=jz[1][1]=m;
12         jz[0][0]=m-1;
13         jz[0][1]=0;
14     }
15     jz22 operator * (jz22 const &a)const
16     {
17         jz22 b;
18         for(int i = 0;i<2;++i)
19             for(int j=0 ;j<2;++j)
20             {
21                 b.jz[i][j]=0;
22                 for(int k=0;k<2;++k)
23                     b.jz[i][j]=(b.jz[i][j]+jz[i][k]*a.jz[k][j])%mod;
24             }
25         return b;
26     }
27 };
28 jz22 pow(jz22 a,ll p)
29 {
30     if(p==1)return a;
31     jz22 ans=pow(a,p/2);
32     ans=ans*ans;
33     ans.jz[0][0]%=mod;
34     ans.jz[0][1]%=mod;
35     ans.jz[1][0]%=mod;
36     ans.jz[1][1]%=mod;
37     if(p%2)
38         {
39             ans=ans*a;
40             ans.jz[0][0]%=mod;
41             ans.jz[0][1]%=mod;
42             ans.jz[1][0]%=mod;
43             ans.jz[1][1]%=mod;
44         }
45     return ans;
46 }
47 int main()
48 {
49     cin>>m>>n;
50     n--;
51     m%=mod;
52     jz22 a,b,c;
53     b=pow(a,n);
54     cout<<b.jz[1][0];
55     return 0;
56 }
View Code

 

posted on 2019-09-04 16:22  gryzy  阅读(261)  评论(0编辑  收藏  举报

导航