題意:
n位數,給定m個區間使得任意區間數乘積爲9的倍數,求多少種構造方法。
思路:
要使得區間數的乘積爲9的倍數,至少得2個3/6,或者1個0/9。
定義代表到了第位時,最後兩個符合條件的數的位置。
對於每個區間,設置代表第個位置的最小區間的左下標。因爲相同右下標的區間,左下標更大肯定還是都成立,而且區間越小方案數相對越多。
那麼對於第個位置,
可以填 3/6,那麼
- 第個位置填1/2/4/5/7/8
- 第個位置填 3/6
- 第個位置填 0/9
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
ll L[55],f[55][55][55];
int main() {
int n,m;
while(~scanf("%d%d",&n,&m)) {
memset(L,0,sizeof(L));
memset(f,0,sizeof(f));
for(int i = 1;i <= m;i++) {
ll l,r;scanf("%lld%lld",&l,&r);
L[r] = max(L[r],l);
}
f[0][0][0] = 1;
for(int i = 1;i <= n;i++) {
for(int j = L[i - 1];j <= i;j++) {
for(int k = L[i - 1];k <= j;k++) {
f[i][j][k] = (f[i][j][k] + f[i - 1][j][k] * 6 % mod) % mod;
f[i][i][j] = (f[i][i][j] + f[i - 1][j][k] * 2 % mod) % mod;
f[i][i][i] = (f[i][i][i] + f[i - 1][j][k] * 2 % mod) % mod;
}
}
}
ll ans = 0;
for(int i = L[n];i <= n;i++) {
for(int j = L[n];j <= i;j++) {
ans = (ans + f[n][i][j]) % mod;
}
}
printf("%lld\n",ans);
}
return 0;
}