洛谷P3197 [HNOI2008]越狱 题解

传送门

洛谷P3197 [HNOI2008]越狱

• 监狱有连续编号为 1…N 的 N 个房间,每个房间关押一个犯人,有 M 种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱。
这道题ROS自己按照网上集训时思路手敲了一下。
ROS讲解:
首先先求一下所有的可能性:M^N(^为求次方的符号)  ①
然后我们发现求有多少种状态不会越狱比较难。
那就“正难则反”不就好了!
求一下有多少种情况会越狱。
对于一种排布来说只有会越狱和不会越狱两种情况。
所以不会越狱的情况数=总情况数-会越狱的情况数
好的我们来看怎么求会越狱的情况数。
根据乘法原理有:
对第一个人来说他有M种宗教可以选择
对第二个人来说他不能选择和第一个人一样的宗教所以有M-1种宗教可以选择
对第三个人来说他不能选择和第二个人一样的宗教所以有M-1种宗教可以选择
.
.
.
所以根据乘法原理有:
会越狱的情况数:N*(M-1)^(N-1)(^为求次方的符号)  ②
所以用①-②就好了!
是不是很简单!
 
好的ROS到洛谷上敲这道题的代码,第一次10分。。。。
原来取模没有对每个结果都取导致了溢出(或者得到负数结果)的问题。
好的对每个结果取模改一下。
 
然后第二次提交70分。
这又是什么情况?
最后上讨论一看发现是c++的玄学取模导致的,我们需要在最后一步(输出答案的一步)把原先的((ksm(m,n)%esp)-((ksm(m-1,n-1)%esp)*m))%esp改成((ksm(m,n)%esp)-((ksm(m-1,n-1)%esp)*m)%esp+esp)%esp防止出现玄学负数解
整体AC代码:
 1 #include<bits/stdc++.h>
 2 #define esp 100003
 3 #define ll long long
 4 using namespace std;
 5 ll m,n;
 6 ll ksm(ll a,ll b){
 7     if(a==1||a==0) return a;
 8     if(b==1) return a;
 9     if(b==0) return 1;
10     ll tmp=ksm(a,b/2);
11     if(b&1) return (tmp%esp)*(tmp%esp)%esp*(a%esp)%esp; 
12     return (tmp%esp)*(tmp%esp)%esp;
13 }
14 int main(){
15     scanf("%lld%lld",&m,&n);
16     printf("%lld",((ksm(m,n)%esp)-((ksm(m-1,n-1)%esp)*m)%esp+esp)%esp);
17     return 0;
18 }

代码量少但是思维含量还是有的。

 

posted @ 2020-03-04 23:42  Robertspot  阅读(246)  评论(0编辑  收藏  举报