牛客小白月赛8 - E - 诡异数字 数位DP

牛客小白月赛8 - E - 诡异数字

题意:

    求区间中,满足限制条件的数字的个数。 限制条件就是某些数字不能连续出现几次。

思路:

    比较裸的数位DP, DP数组开一个dp【len】【x】【cnt】 表示长度为len,x这个数字连续出现cnt次的个数。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
typedef long long ll; using namespace std; const int mod = ; int dp[][][];
int cnt[],shu[]; ll swdp(int len, int x,int sum, bool limit){
if(len == )return ;
if(!limit && dp[len][x][sum]) return dp[len][x][sum]; int mx = limit ? shu[len] : ;
ll res = ;
for(int i=; i<=mx; i++){
if(x==i && sum + > cnt[x])continue;
if(x==i) res = (res + swdp(len-,x,sum+, limit && i == mx)) % mod;
else res = (res + swdp (len-,i,,limit && i == mx))%mod; }
return limit?res:dp[len][x ][sum] = res;
} ll solve(ll x){
if(x == -)return ;
int k = ;
while(x > ){
shu[++k] = x % ;
x /= ;
}
return swdp(k, , , true);
}
int main(){
int t,n; scanf("%d", &t);
ll le,ri;
while(t--) {
for(int i=; i<=; i++)cnt[i] = ;
memset(dp,,sizeof(dp));
scanf("%lld%lld%d", &le, &ri, &n);
while(n--) {
int x,len;
scanf("%d%d", &x, &len);
cnt[x] = min(cnt[x] , len);
} printf("%lld\n", (solve(ri) - solve(le-) + mod)%mod);
} return ;
}
上一篇:$(document).ready、body.Onload()和 $(window).load的区别


下一篇:牛客网 牛客小白月赛5 I.区间 (interval)-线段树 or 差分数组?