解题报告 Valentine’coat

 

1.        题目

2Valentine’s Coat(coat)

描述

今天是情人节,小杉在参加一个valentine’s party!

Oh,it sounds good.

现在已经是晚上10点了,参加partyn个人很无聊,于是开始玩一个游戏。

每个人先穿一件白外套,再站成一个圈,然后给每件外套上色。总共有k种颜色可以上。

一个可爱的上色方案应该满足对于每一个人,他身边的两个人所穿的外套颜色都和他所穿的不同。

小杉现在想知道总共有多少种可爱的上色方案。

输入格式

一行两个整数n,k(1<=n<=3000,1<=k<=10)

输出格式

仅有一行,一个整数,为上色方案数对19900801取模的结果

样例输入

2 2

样例输出

2

样例解释

譬如小杉和小小杉玩这个游戏,给小杉上第一种颜色,给小小杉上第二种颜色,或者相反,都是可爱的上色方案,总共两种。

 

2.        题目实质

这个模型很简单,就是给一个环形元素集合上色,相邻元素不能颜色相同。求上色方案数。

3.        算法

仍旧是递推。

首先,显然,当 n=1 时, k 即为所求。

由于每个人是不同的,我们这样考虑,把环拉成一条线,令f[i]i个数,首尾颜色不同的方案数。f[i]可以由首尾相同的i-1个数再加上一个不同于首尾的数得到,或者由首尾不同的i-1数再加上一个不同于首尾的数得到,前者为f[i-2]*(k-1)(首尾相同的i-1个数和首尾不同的i-2个数是等价的),后者为f[i-1]*(k-2)。初始为f[1]=0f[2]=k*(k-1)

于是我们得到f[i]=f[i-1]*(k-2)+f[i-2]*(k-1),即(f[i]+f[i-1])=(f[i-1]+f[i-2])*(k-1),而f[1]+f[2]=k*(k-1),于是f[i]+f[i+1]=k*(k-1)^i,即f[i+1]=-f[i]+k*(k-1)^i,即(-1)^(i+1)f[i+1]=(-1)^if[i]-k*(1-k)^i,换元后使用等比数列求和公式可得f[i]=(k-1)^i+(-1)^i*(k-1)。注意若n=1,应输出k而不是0

当然,使用f[i]=f[i-1]*(k-2)+f[i-2]*(k-1)递推也是可以的。

4.        注意事项

这个题不要用快速幂,第一, NOIP 不怎么考,第二,会报栈溢出的,就像 std 一样。

5.        程序代码

绝恋LOVE  (pascal)

program coat(input,output);

var

   ans : int64;

   n,k : longint;

function power(x,y: longint ):int64;

var

   i : longint;

begin

   power:=1;

   for i:=1 to y do

      power:=(power*x) mod 19900801;

end; { power }

begin

   assign(input,'coat.in');reset(input);

   assign(output,'coat.out');rewrite(output);

   readln(n,k);

   ans:=0;

   if (n=1)and(k=1) then

      ans:=1

   else

      if (n mod 2=1) then

        ans:=power(k-1,n)-(k-1)

      else

        ans:=power(k-1,n)+(k-1);

   writeln(ans);

   close(input);

   close(output);

end.

 

原文地址:https://www.cnblogs.com/SueMiller/p/2132322.html