HAUTOJ 1265

题目描述

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朵花颜色相同。保证lr且 |(rlmod 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);
            }

        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值