越狱(信息学奥赛一本通 1618)

【题目描述】

原题来自: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≤108,1≤n≤1012 。

 


 

当然一开始我并没有想到可以用快速幂的方法,看到题目以后马上联想到DP啥子的,然鹅事实证明用快速幂最为简便

直接正面刚去求有多少种状态的话肯定是会爆掉而且还没有什么好方法,那么正难则反,我们可以通过用总状态数-不会越狱的状态数来得到答案

并且不难发现,总状态数=m^n,不会越狱的状态数=(m-1)^(n-1)*m(乘法原理,第一个监狱的犯人可能有m种状态,而与其相邻的第二个监狱就只能有m-1种状态,同理,其余的监狱也只能有m-1种状态),这样的话,用快速幂就特别方便啦!(σ゚∀゚)σ..:*☆ 

代码走一波:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const long long M=100003;
 4 long long m,n;//这道题基本上都是用long long类型,不然会像我一样被卡5个点死活过不去ε(┬┬﹏┬┬)3
 5 long long read()
 6 {
 7     long long x=0,f=1;
 8     char ch=getchar();
 9     while(ch<'0'||ch>'9')
10     {
11         if(ch=='-') f=-1;
12         ch=getchar();
13     }
14     while(ch>='0'&&ch<='9')
15     {
16         x=x*10+ch-'0';
17         ch=getchar();
18     }
19     return x*f;
20 }
21 void write(int x)
22 {
23     if(x<0)
24     {
25         putchar('-');
26         x=-x;
27     }
28     if(x>9) write(x/10);
29     putchar(x%10+'0');
30 }
31 
32 long long ff(long long x,long long y)
33 {
34     long long ans=1;
35     while(y)
36     {
37         if(y&1)ans=ans*x%M;
38         x=x*x%M;
39         y>>=1;
40     }
41     return ans;
42 }
43 int main()
44 {
45     m=read();n=read();
46     if(n<2)return 0*puts("0");
47     printf("%lld\n",((ff(m,n)-m*ff(m-1,n-1)%M)%M+M)%M);
48     return 0;
49 }

转载于:https://www.cnblogs.com/ljy-endl/p/11380325.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值