举火燎天

来源:互联网 发布:设计家具的软件 编辑:程序博客网 时间:2024/05/22 06:57

问题描述 Problem Description

征夷王将越南(南夷) 攻下来之后, 决定用 N 个火炬摆成一个圆圈, 围住越南的都城,以举火燎天宣告自 己的胜利。 这 N 个火炬的位置已经固定了, 但是, 每个火炬的颜色都没定, 总共有 M 种颜色的火炬。 为了显示我们中华文化的博大精深, 征夷王决定, 相邻的火炬的颜色不能相同。 现在征夷王想知道, 满足他要求的方案有多少个。 由于火炬的位置已经固定, 所以即便旋转翻转之后两种方案相同也视作不同方案。


输入描述 Input Description

输入一行两个正整数 NM , 意义如上所述。


输出描述 Output Description

输出一行一个正整数, 代表方案总数。


输入样例 Sample Input

3 4


输出样例 Sample Output

24


数据范围 Data Size

对于 100% 的数据,1N,M100


分析 I Think

先说特殊情况,当 n=1 时,ans=m
再来普遍情况。记 fi,0 表示在第 i 个地方火炬颜色与第 1 个火炬颜色一样的方案数, fi,1 表示在第 i 个地方火炬颜色与第 1 个火炬颜色不同的方案数。要与第 1 个火炬颜色相同,只能在第 i 个火炬只有 1 种可能,也就是说 fi,0=fi1,1 。要与第 1 个火炬颜色不同,如果上一个颜色与第 1 个火炬颜色不同那么有 m2 种方案,与其相同就有 m1 种方案,也就是 fi,1=(m2)fi1,1+(m1)fi1,0


代码 Code

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const LL Mod = 100000000;struct bign{    LL a[100];    int len;    bign(LL x = 0){        this->clear();        a[0] = x;    }    bign operator + (const bign &h){        bign ans;        ans.len = max(len,h.len)+1;        for(int i=0;i<ans.len;++i){            ans.a[i] = ans.a[i]+h.a[i]+a[i];            ans.a[i+1] += ans.a[i]/Mod;            ans.a[i] %= Mod;        }        if(!ans.a[ans.len-1])            --ans.len;        return ans;    }    bign operator * (const bign &h){        bign ans;        ans.len = len+h.len;        for(int i=0;i<len;++i)            for(int j=0;j<h.len;++j)                ans.a[i+j] = a[i]*h.a[j];        for(int i=0;i<ans.len;++i){            ans.a[i+1] += ans.a[i]/Mod;            ans.a[i] %= Mod;        }        if(!ans.a[ans.len-1])            --ans.len;        return ans;    }    void display(){        printf("%lld",a[len-1]);        for(int i=len-2;i>=0;--i)            printf("%08lld",a[i]);    }    void clear(){        memset(a,0,sizeof a);        len = 1;    }}f[120][2],s1,s2;LL n,m;int main(){    scanf("%lld%lld",&n,&m);    if(n == 1){        printf("%lld",m);        return 0;    }    f[1][1].a[0] = m;    s1.a[0] = m-1;    s2.a[0] = m-2;    for(int i=2;i<=n;++i){        f[i][1] = f[i-1][0];        f[i][0] = f[i-1][0]*s2+f[i-1][1]*s1;    }    f[n][0].display();    return 0;}
0 0