题目链接: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; } }