Modulo Nine

题目链接:https://ac.nowcoder.com/acm/contest/7959/D

题意:求长度为n的一个由0~9组成的数字串,满足m个限定,每个限制条件规定[Li,Ri]之间的数字相乘结果%9为0,求不同数字串的个数。

思路:dp,区间一段数相乘%9=0,那区间中有一个0或一个9即可,或者3和6中含有两个数即可。所以可以把数分成3类,0,9一类;3,6一类,1,2,4,5,7,8一类。

设dp[i][j][k]表示dp到第i位时,最后的两个使限制条件得以满足的数字的位置为j,k时答案数。(j>=k,k>=a[i])。所以:

         dp[i+1][j][k]=(dp[i+1][j][k]+6*dp[i][j][k])%mod;                              第3类数字

    dp[i+1][i+1][j]=(dp[i+1][i+1][j]+2*dp[i][j][k])%mod;                       第2类数字

    dp[i+1][i+1][i+1]=(dp[i+1][i+1][i+1]+2*dp[i][j][k])%mod;               第1类数字

最后再求和dp[n][i][j]即可。

#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll mod=1000000007;
ll dp[55][55][55];
int a[55];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        memset(dp,0,sizeof(dp));
        memset(a,0,sizeof(a));
        while(m--)
        {
            int l,r;
            cin>>l>>r;
            a[r]=max(a[r],l);
        }
        dp[0][0][0]=1;
        for(int i=0; i<n; i++)
        {
            for(int j=a[i]; j<=i; j++)
            {
                for(int k=a[i]; k<=j; k++)
                {
                    dp[i+1][j][k]=(dp[i+1][j][k]+6*dp[i][j][k])%mod;
                    dp[i+1][i+1][j]=(dp[i+1][i+1][j]+2*dp[i][j][k])%mod;
                    dp[i+1][i+1][i+1]=(dp[i+1][i+1][i+1]+2*dp[i][j][k])%mod;
                }
            }
        }
        ll ans=0;
        for(int i=a[n]; i<=n; i++)
        {
            for(int j=a[n]; j<=i; j++)
                ans=(ans+dp[n][i][j])%mod;
        }
        cout<<ans<<endl;
    }
}

 

posted @ 2020-10-05 16:42  ~zcb  阅读(153)  评论(0编辑  收藏  举报