您的位置:首页 > 其它

举火燎天

2016-07-08 16:44 197 查看

举火燎天

问题描述

征夷王将越南(南夷)攻下来之后,决定用 N 个火炬摆成一个圆圈,围住越南的都城,以举火燎天宣告自己的胜利。

这 N 个火炬的位置已经固定了,但是,每个火炬的颜色都没定,总共有 M 种颜色的火炬。

为了显示我们中华文化的博大精深,征夷王决定,相邻的火炬的颜色不能相同。

现在征夷王想知道,满足他要求的方案有多少个。

由于火炬的位置已经固定,所以即便旋转翻转之后两种方案相同也视作不同方案。

输入

输入文件名为Lights.in。

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

输出

输出文件名为Lights.out。

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

输入样例

3 4

输出样例

24

数据范围

对于 100% 的数据,1<=N,M<=100

Solution

设 f[i][1] 表示第 i 个火炬与第 1 个火炬颜色相同的方案个数,而 f[i][0] 表示第 i 个火炬与第 1 个火炬颜色不同的方案个数。

f[1][0]=0,f[1][1]=m

f[i][0]=f[i−1][1]∗(m−1)+f[i−1][0]∗(m−2)

f[i][1]=f[i−1][0]

Code

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define LL long long
#define MOD 100000000
#define Max(x,y) ((x)>(y)?(x):(y))

struct bign{
LL s[100],len;
bign(){
memset(s,0,sizeof s);
len=1;
}
bign operator = (const LL num){
s[1]=num;len=1;
return *this;
}
bign operator * (const LL num){
bign c;c.len=len+1;
for(LL i=1;i<=len;i++){
c.s[i+1]=(c.s[i]+s[i]*num)/MOD;
c.s[i]=(c.s[i]+s[i]*num)%MOD;
}
while(!c.s[c.len]&&c.len>1)c.len--;
return c;
}
bign operator + (const bign &num){
bign c;c.len=Max(len,num.len);
for(LL i=1;i<=c.len;i++){
c.s[i+1]=(c.s[i]+s[i]+num.s[i])/MOD;
c.s[i]=(c.s[i]+s[i]+num.s[i])%MOD;
}
if(c.s[c.len+1])c.len++;
return c;
}
void out(){
for(LL i=len;i>=1;i--){
if(len==i)printf("%lld",s[len]);
else printf("%08lld",s[i]);
}
}
};

LL n,m;

bign f[110][2];

int main(){

freopen("Lights.in","r",stdin);
freopen("Lights.out","w",stdout);

scanf("%lld%lld",&n,&m);
if(n==1){
printf("%lld\n",m);
return 0;
}
else if(n==2){
LL ans=m*(m-1);
printf("%lld\n",ans);
return 0;
}
else{
f[1][1]=m;f[0][0]=0;
for(int i=2;i<=n;i++){
f[i][1]=f[i-1][0];
f[i][0]=f[i-1][0]*(m-2)+f[i-1][1]*(m-1);
}
f
[0].out();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: