BZOJ 1008 越狱

题目如下:

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

此题,一看数据,首先想到log级别的算法。然后再看题目,数据结构肯定是没指望了。求的是状态数,所以考虑递推和乘法原理。若尝试递推,会发现递推式和通项公式都很难求出来。所以我们换一个角度。正着求求不出来,不妨试试倒着求。很显然的是------所有的状态数=MN。若采用倒着求的方式,则下一个需要计算的是,不发生越狱的情况数=M*(M-1)N-1。为什么呢?对于每一种宗教(M)则会有M-1种宗教和他相邻且不会发生越狱,那么这m-1种宗教的排列方式又有多少种呢?即(M-1)N-1种,所以共有M*(M-1)N-1种情况不会发生越狱。这下明了了。所以答案就是所有情况数减去不发生越狱的情况数--------MN-M*(M-1)N-1。快速幂即可。

#include<cstdio>
#include<iostream>
#define mod 100003
#define ll long long int
using namespace std;
ll m,n;
ll quick(ll a,ll n)
{
    ll b=1;
    while(n>0){
        if(n&1){
          b=b*a%mod;
        }
        a=a*a%mod;
        n=n>>1;
    }
    return b;
}
int main()
{
    scanf("%lld%lld",&m,&n);
    m%=mod;
    ll ans1=quick(m,n)%mod;
    ll ans2=m*quick(m-1,n-1)%mod;
    ll ans=ans1+mod-ans2;
    ans%=mod;
    printf("%lld",ans);
}
posted @ 2015-08-01 17:49  Martrix99  阅读(98)  评论(0编辑  收藏