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;
}

     
 
				
时间: 2024-10-19 09:53:30

zoj 3538 递推的相关文章

ZOJ 3690 &amp; HDU 3658 (矩阵快速幂+公式递推)

ZOJ 3690 题意: 有n个人和m个数和一个k,现在每个人可以选择一个数,如果相邻的两个人选择相同的数,那么这个数要大于k 求选择方案数. 思路: 打表推了很久的公式都没推出来什么可行解,好不容易有了想法结果WA到天荒地老也无法AC.. 于是学习了下正规的做法,恍然大悟. 这道题应该用递推 + 矩阵快速幂. 我们设F(n) = 有n个人,第n个人选择的数大于k的方案数: G(n) = 有n个人,第n个人选择的数小于等于k的方案数: 那么递推关系式即是: F(1)=m?k,G(1)=k F(n

[递推dp] zoj 3747 Attack on Titans

题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5170 Attack on Titans Time Limit: 2 Seconds      Memory Limit: 65536 KB Over centuries ago, mankind faced a new enemy, the Titans. The difference of power between mankind and their newf

ACM学习历程——ZOJ 3822 Domination (2014牡丹江区域赛 D题)(概率,数学递推)

Description Edward is the headmaster of Marjar University. He is enthusiastic about chess and often plays chess with his friends. What's more, he bought a large decorative chessboard with N rows and M columns. Every day after work, Edward will place

POJ 3090 ZOJ 2777 UVALive 3571 Visible Lattice Points(用递推比用欧拉函数更好)

题目: Description A lattice point (x, y) in the first quadrant (x and y are integers greater than or equal to 0), other than the origin, is visible from the origin if the line from (0, 0) to (x, y) does not pass through any other lattice point. For exa

[递推+dfs]ZOJ 3436. July Number

题目大意: 将一个数字的相邻两位的差(的绝对值)组成一个新的数字,不断重复,如果最后得到7,就称这个数为July Number,比如9024 – 922 – 70 – 7.题目要求1e9范围内给定区间[a, b]里July Number的个数. 思路:逆向递推,既然题目求能化成 7 的数的个数,那么就从 7 逆着找出去 18 ,29,70,81,92等,(要注意的就是:还有从07,007.....等找出去的,每个数同理: 代码: /* SKY */ #include<iostream> #in

hdu 1396 Counting Triangles (递推)

Counting Triangles Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2012    Accepted Submission(s): 966 Problem Description Given an equilateral triangle with n the length of its side, program to

zoj 3538 Arrange the Schedule

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 c

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

hdu 1267 递推

下沙的沙子有几粒? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4326    Accepted Submission(s): 2268 Problem Description 2005年11月份,我们学校参加了ACM/ICPC 亚洲赛区成都站的比赛,在这里,我们获得了历史性的突破,尽管只是一枚铜牌,但获奖那一刻的激动,也许将永远铭刻