zoj 3538 递推

题目连接:Click here

Arrange the Schedule

Time Limit: 1 Second      Memory Limit: 65536 KB

In Summer 2011, the ZJU-ICPC Team has a n-days training schedule. ZJU-ICPC Team has been divided into 4 Group: Akiba, BiliBili, CIA, Double(Group A, B, C, D). There is a group in charge of the training problems on each day. As the ICPC Team manager, you have to decide which team is in charge of the problems on each day. But there are something you should rememeber:

1. No team is able to provide problems on two adjacent days.
2. There are m days in the Summer 2011 that which group is in charge of the problems have been decided. (e.g. Akiba provides problems on day 1, BiliBili provides problems on day 6. And these can not be changed)

How many ways are there to arrange the schedule? Output the answer modulo 1000000007.

Input

There are multiple test cases(less than 50). Each case contains two integers n, m (1 ≤ n ≤ 10000000, 0 ≤ m ≤ 10), which indicate the number of days in Summer 2011 and the number of days that have been decided.
Following m lines. Each line contains one integer ai and one upper letter Ch ('A' ≤ Ch ≤ 'D'), indicate that on day ai (1 ≤ ai ≤ n), group Ch is in charge of the problems. We guarantee that all ai are distinct. There is a blank line after each input case.

Output

For each case, output a single line containing the answer, the number of the ways to arrange the schedule modulo 1000000007.

Sample Input
3 2
1 A
3 C

2 1
1 D

Sample Output
2
3
Hint
Case 1:
2 ways: ABC, ADC.
Case 2:
3 ways: DA, DB, DC.
 
 
 
 
思路:这道题不太难,递推公式即可,但是代码实现得细心。好像递推公式也有多种,我的递推思路如下:
dp[i][0]:由第1个人安排第i天的任务,dp[i][1]:由第2个人安排第i天的任务,dp[i][2]:由第3个人安排第i天的任务,dp[i][3]:由第4个人安排第i天任务;
当扫描到第i天的时候,第i天的情况分为两种
(1):第i天安排已经固定了,那么由于同一个人不能在相邻两天出题,假设这一天是由A来安排,
         那么dp[i][0]=dp[i-1][1]+dp[i][2]+dp[i-1][3]; dp[i][1]=dp[i][2]=dp[i][3]=0;
 (2): 第i天安排没有固定,也就是安排第i天任务的人可以是A,B,C,D中的任何一个,同理也可由第i-1天推到第i天,得出递推公式dp[i][j]=dp[i-1][k1]+dp[i-1][k2]+dp[i-1][k3];
如果没有m的限制,直接矩阵快速幂即可,现在就因为m的存在,要分段快速幂;
注意细节;
#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <algorithm>
const int MOD=1000000007;
using namespace std;
typedef long long ll;
int n,m;
ll in[8];


// 矩阵运算
struct matrix
{
  ll f[5][5];
};

matrix mul(matrix a,matrix b)
{
  matrix c;
  memset(c.f,0,sizeof(c.f));
  for(int i=0;i<4;i++)
     for(int j=0;j<4;j++)
       for(int k=0;k<4;k++)
       {
         c.f[i][j]+=(a.f[i][k]*b.f[k][j])%MOD;
         c.f[i][j]%=MOD;
       }
  return c;
}

matrix quick_mod(matrix a,int b)
{
   matrix s;
   memset(s.f,0,sizeof(s.f));
   for(int i=0;i<4;i++)s.f[i][i]=1;
   while(b)
   {
     if(b&1)
        s=mul(s,a);
     b/=2;
     a=mul(a,a);
   }
   return s;
}

matrix mat;


//............

struct node
{
  int day;
  char s[10];
}a[110];
bool cmp(node n1,node n2)
{
   return n1.day<n2.day;
}

void init()
{
  in[1]=in[2]=in[3]=in[4]=1;
}

int main()
{
   mat.f[0][0]=0,mat.f[0][1]=1,mat.f[0][2]=1,mat.f[0][3]=1;
   mat.f[1][0]=1,mat.f[1][1]=0,mat.f[1][2]=1,mat.f[1][3]=1;
   mat.f[2][0]=1,mat.f[2][1]=1,mat.f[2][2]=0,mat.f[2][3]=1;
   mat.f[3][0]=1,mat.f[3][1]=1,mat.f[3][2]=1,mat.f[3][3]=0;
   while(scanf("%d%d",&n,&m)!=EOF)
   {
     for(int i=1;i<=m;i++)scanf("%d%s",&a[i].day,a[i].s);
     sort(a+1,a+1+m,cmp);
     init();

     int cur=1;
     for(int i=1;i<=m;i++)
     {
        int d=a[i].day;
        if(d==1)
        {
              if(a[i].s[0]=='A')
              {
                 in[1]=1;
                 in[2]=in[3]=in[4]=0;
              }
              if(a[i].s[0]=='B')
              {
                 in[2]=1;
                 in[1]=in[3]=in[4]=0;
              }
              if(a[i].s[0]=='C')
              {
                 in[3]=1;
                 in[1]=in[2]=in[4]=0;
              }
              if(a[i].s[0]=='D')
              {
                  in[4]=1;
                  in[1]=in[2]=in[3]=0;
              }
           continue;
        }

        if(d-1-cur>0)
        {
         matrix tmp=mat;
         tmp=quick_mod(tmp,d-1-cur);
         ll a1=in[1]*tmp.f[0][0]%MOD+in[2]*tmp.f[0][1]%MOD+in[3]*tmp.f[0][2]%MOD+in[4]*tmp.f[0][3]%MOD;
         ll a2=in[1]*tmp.f[1][0]%MOD+in[2]*tmp.f[1][1]%MOD+in[3]*tmp.f[1][2]%MOD+in[4]*tmp.f[1][3]%MOD;
         ll a3=in[1]*tmp.f[2][0]%MOD+in[2]*tmp.f[2][1]%MOD+in[3]*tmp.f[2][2]%MOD+in[4]*tmp.f[2][3]%MOD;
         ll a4=in[1]*tmp.f[3][0]%MOD+in[2]*tmp.f[3][1]%MOD+in[3]*tmp.f[3][2]%MOD+in[4]*tmp.f[3][3]%MOD;
         in[1]=a1%MOD,in[2]=a2%MOD,in[3]=a3%MOD,in[4]=a4%MOD;

        }
        if(a[i].s[0]=='A')
        {
            in[1]=in[2]+in[3]+in[4];
            //if(a[i].day=100)cout<<(in[2]+in[3]+in[4])%MOD<<endl;
            in[2]=in[3]=in[4]=0;
        }
        else if(a[i].s[0]=='B')
        {
            in[2]=in[1]+in[3]+in[4];
            in[1]=in[3]=in[4]=0;
        }
        else if(a[i].s[0]=='C')
        {
            in[3]=in[1]+in[2]+in[4];
            in[1]=in[2]=in[4]=0;
        }
        else
        {
            in[4]=in[1]+in[2]+in[3];
            in[1]=in[2]=in[3]=0;
        }
        cur=a[i].day;
     }

     if(a[m].day!=n)
     {
         matrix tmp=mat;
         tmp=quick_mod(tmp,n-cur);
         ll a1=in[1]*tmp.f[0][0]%MOD+in[2]*tmp.f[0][1]%MOD+in[3]*tmp.f[0][2]%MOD+in[4]*tmp.f[0][3]%MOD;
         ll a2=in[1]*tmp.f[1][0]%MOD+in[2]*tmp.f[1][1]%MOD+in[3]*tmp.f[1][2]%MOD+in[4]*tmp.f[1][3]%MOD;
         ll a3=in[1]*tmp.f[2][0]%MOD+in[2]*tmp.f[2][1]%MOD+in[3]*tmp.f[2][2]%MOD+in[4]*tmp.f[2][3]%MOD;
         ll a4=in[1]*tmp.f[3][0]%MOD+in[2]*tmp.f[3][1]%MOD+in[3]*tmp.f[3][2]%MOD+in[4]*tmp.f[3][3]%MOD;
         in[1]=a1%MOD,in[2]=a2%MOD,in[3]=a3%MOD,in[4]=a4%MOD;
     }
     printf("%lld\n",(in[1]+in[2]+in[3]+in[4])%MOD);
   }
   return 0;
}

     
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值