bzoj1008 [HNOI2008]越狱
1008: [HNOI2008]越狱
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 9635 Solved: 4160
[Submit][Status][Discuss]
Description
监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果
相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱
Input
输入两个整数M,N.1<=M<=10^8,1<=N<=10^12
Output
可能越狱的状态数,模100003取余
Sample Input
2 3
Sample Output
6
HINT
6种状态为(000)(001)(011)(100)(110)(111)
分析:统计方案数的题,要么是dp,要么是数学方法(暴力能过的水题除外),显然,dp是不可行的,n,m的范围如此之大,数组都开不下啊.考虑数学方法。
直接求可能发生冲突的方案数不太好求,那么换个角度思考,用总状态数-不可能发生越狱的状态数就是答案。
显然,每个位置可以选m种宗教,n个位置的方案数就是m^n,考虑第一个位置,可以选m种宗教,第二个位置就只能选m-1种宗教,以后n-2个位置也只能选m-1中宗教,因为总有一种宗教会与相邻的前一个位置的宗教相冲突,那么不可能发生越狱的状态数就是m*(m-1)^(n-1),答案就是m^n-m*(m-1)^(n-1).
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> typedef long long LL; using namespace std; long long n, m,ans1,ans2; const int mod = 100003; long long power(long long a, long long b) { long long ans = 1; while (b) { if (b & 1) ans = (ans * a) % mod; a = (a * a) % mod; b >>= 1; } return ans % mod; } int main() { scanf("%lld%lld", &m, &n); ans1 = power(m, n) % mod; ans2 = (m * power(m - 1, n - 1)) % mod; printf("%lld", (ans1 - ans2 + mod) % mod); return 0; }