题目描述
Hmz为了女装,想给自己做一个长度为n的花环。现在有k种花可以选取,且花环上相邻花的种类不能相同。
Hmz想知道,如果他要求第l朵花和第r朵花颜色相同,做花环的方案数是多少。这个答案可能会很大,你只要输出答案对10^9+7取模的结果即可。
输入
第一行三个整数n,m,k(1≤n≤100000,1≤m≤100000,1≤k≤100000)
接下来m行,每行两个整数l,r,表示要求第l朵花和第r朵花颜色相同。保证l≠r且 |(r−l) mod n| ≠1.
输出
输出m行。对于每一个询问输出一个整数,表示做花环的方案数对10^9+7取模的结果。
样例输入
8 3 2
1 4
2 6
1 3
8 3 3
1 4
2 6
1 3
样例输出
0
2
2
60
108
132
动态规划,做花环,且相邻的不同,要求第l朵和第r朵花是一样的,由此可以得到从第i朵到第i+1朵可能方案
我们可以将第一朵看成固定的颜色,所以如果第i朵花和第一朵花相同的可能有m种,不同的可能有n种,那么第i+1多花和第一朵花相同的情况只能由n得来,且等于n,不同的情况
是(m+n)*(k-1);动态转移方程:a[i+1][0]=a[i][1]+a[i][2];a[i+1][1]=a[i][0]*k-1;a[i+1][2]=(a[i][1]+a[i][2])*(k-2);(其实后面两个可以合并,合并后更好理解)
由题我们可以将花环先连起来再分成两段,切口就是l和r那么就是求一段前后都一样的,和一段前后不相同的求积即可
#include<stdio.h> #include<string> #include<iostream> #include<cstring> #include<math.h> using namespace std; int k; int r,h; int n,m; long long int a[100000][4]; int main() { while(~scanf("%d%d%d",&n,&m,&k)) { a[0][0]=1,a[0][1]=0,a[0][2]=0; a[1][0]=0,a[1][1]=(k-1)%1000000007,a[1][2]=0; for(int i=2;i<n;i++) { a[i][0]=(a[i-1][1]+a[i-1][2])%1000000007; a[i][1]=a[i-1][0]*(k-1)%1000000007; a[i][2]=a[i-1][1]*(k-2)%1000000007+a[i-1][2]*(k-2)%1000000007; } while(m--) { if(k==2) { scanf("%d%d",&r,&h); if((h-r)%2==0) printf("2\n"); else printf("0\n"); } else { scanf("%d%d",&r,&h); int p1,p2; p1=max(r,h)-min(r,h); p1=p1%n;//前后相同的 p2=n-p1-1;//前后不同的 int s; s=(k*a[p1][0]%1000000007*(a[p2][1]+a[p2][2])%1000000007); printf("%d\n",s); } } } }