您的位置:首页 > 其它

NOIP16提高组赛前训练20-day2 T2:种花 flower(组合数学)

2016-11-17 13:36 337 查看

NOIP16提高组赛前训练20-day2 T2:种花 flower

题目描述:

OI太可怕了,我决定回家种田.

我在后院里开辟了一块圆形的花圃,准备种花.种花是一种艺术,通过一定技术手法,花材的排列组合会让花变得更加的赏心悦目,这就是花艺.

当然你知道,我在种田之前是OIer,所以我不懂花艺,只会排列组合.我把花圃从圆心向外画线,分成了N块扇形,分别编号为1,2,3…..N,再从村里的商店采购了M种花.然后我大胆的决定:花圃中的每块只种M种花中的一种,相邻的两块不能种同一种花.我反应比较慢,所以我请来了机房里手速最快的强袭黯灭勋章鱼人守卫来帮我,让他试一下每种排列,看看哪种最令人赏心悦目.

有一些人,他们的美丽就在身边,也许就在自己身上,像艺术家一样,他们的眼光独到特别,可就因为他们不是艺术家,他们不被人们认可,被称之为另类.简单真实的事情总可以绽放最鲜艳的花,我欣赏这样的人的心理,当然拒绝粗鲁地对待一切.

正想着,他居然告诉我已经尝试完了.这怎么可能?这可一共有…….多少种方案来着?

众所周知的是,我的智商很低.

我想知道种花的方案一共有几种.

输入格式:

仅一行,包含两个整数,分别为N和M.

输出格式:

仅一行,包含一个整数,表示方案数.这个数可能很大,你只需要输出这个数对1000000007取模的结果.

样例输入:

3 3

样例输出:

6

数据范围:

对于20%的数据,0

时间限制:

1S

空间限制:

128M

题目分析:

数据辣么大,显然是要推导式子的.

抽象出来就是个染色问题,设当前有n块,m种颜色去染.

设答案为an,那么对于第一块可以染m种颜色,其余2~n块只能染m-1种颜色,那么实际上就有an=m(m−1)n−1,但是这当中计算了第一块与第n块同色的情况.而若将第一块和最后一块看成一块,实际上这些情况的个数就为an−1,那么就有

an=m(m−1)n−1−an−1

将an−1用an−2代替,则有

an=m(m−1)n−1−m(m−1)n−1+an−2

an=m(m−1)n−1−m(m−1)n−2+...+(−1)nm(m−1)

an=m[(m−1)n−1−(m−1)n−2+...+(−1)n(m−1)]

而中括号里面的实际上就是一个等比数列,令b1=(−1)n(m−1),bn=(1−m)bn−1,则有数列{b}的前n项公式为Tn=(−1)n(m−1)[1−(1−m)n−1]m

an=mTn

an=(m−1)n+(−1)n(m−1)

参考资料:百度文库 涂色问题的解题思路2

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

typedef long long ll;
const int MOD=1000000007;

ll read()
{
char ch=getchar();ll ret=0,flag=1;
while(ch<'0'||ch>'9') {if(ch=='-') flag=-1; ch=getchar();}
while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*flag;
}

ll pow_mod(ll x,ll y)
{
ll ans=1;
while(y>0) {
if(y&1) (ans*=x)%=MOD;
(x*=x)%=MOD;y>>=1;
}
return ans;
}

int main()
{
ll N=read(),M=read();
if(N==1) {printf("%lld",M);return 0;}
ll ans=pow_mod(M-1,N);
if(N&1) ans-=(M-1);
else ans+=(M-1);
(ans+=MOD)%=MOD;//注意ans可能为负数
printf("%lld",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: