【Educational Codeforces Round 53 (Rated for Div. 2) E. Segment Sum】 数位DP
2018-11-14 03:23
363 查看
E. Segment Sum
题意
题意很简单,求l到r之间的所有数中不同数位数不超过k的数之和题意很简单,求l到r之间的所有数中不同数位数不超过k的数之和题意很简单,求l到r之间的所有数中不同数位数不超过k的数之和
1<=l<=r<=1018 1<=k<=101<=l<=r<=10^{18} \ \ 1<=k<=101<=l<=r<=1018 1<=k<=10
做法
一眼就知道是数位dp一眼就知道是数位dp一眼就知道是数位dp
而且我们也很容易想到状态的定义而且我们也很容易想到状态的定义而且我们也很容易想到状态的定义
数位dp时要往下传递都有哪些数位出现过,这个状态是(1<<10)的数位dp时要往下传递都有哪些数位出现过,这个状态是(1<<10)的数位dp时要往下传递都有哪些数位出现过,这个状态是(1<<10)的
由于我们要统计和,每个状态要保存两个值由于我们要统计和,每个状态要保存两个值由于我们要统计和,每个状态要保存两个值
满足状态的数字个数和当前状态数字对答案的贡献满足状态的数字个数和当前状态数字对答案的贡献满足状态的数字个数和当前状态数字对答案的贡献
坑点
由于本题中前导0对状态有影响,注意数位dp时前导0的问题由于本题中前导0对状态有影响,注意数位dp时前导0的问题由于本题中前导0对状态有影响,注意数位dp时前导0的问题
代码
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; typedef long long ll; const ll Mod = 998244353ll; typedef pair<ll,ll> pll; #define Se second #define Fi first ll l,r,k; ll pow_[20]; int cal(ll x) { int ans=0; while(x) { if(x&1) ans++; x/=2; } return ans; } pll dp[20][1<<12][2]; ll a[20]; pll dfs(ll len,ll state,bool limit,bool lead) { if(len==0) return pll(1,0);//遍历结束,无需算对答案的贡献,但是要像正常数位dp一样统计满足条件的个数 if(!limit&&dp[len][state][lead].Se) return dp[len][state][lead];//注意带前导0的数位dp套路 pll ans=pll(0,0); int up=limit?a[len]:9; for(int i=0;i<=up;i++) { ll temp=state|((lead||i)<<i); //若当前有前导0而且当前数位为0,则状态不更新 if(cal(temp)>k) continue; //不满足答案的状态要去掉 pll tmp=dfs(len-1,temp,limit&&i==a[len],lead||i); ans.Fi=(ans.Fi+tmp.Fi)%Mod; ans.Se=(ans.Se+tmp.Se+(1LL*i*pow_[len-1]%Mod*tmp.Fi)%Mod)%Mod; //当前数位对答案的贡献为当前数位所代表的值为i*pow[len-1] //当前数位为i的数字个数为tmp.Fi //总贡献为:i*pow_[len-1]%Mod*tmp.Fi } return dp[len][state][lead]=ans; } ll solve(ll x) { for(int i=0;i<20;i++) { for(int j=0;j<(1<<12);j++) { for(int l=0;l<2;l++) { dp[i][j][l].Fi=0; dp[i][j][l].Se=0; } } } memset(a,0,sizeof(a)); int len=0; while(x) { a[++len]=x%10; x/=10; } return dfs(len,0,true,0).Se%Mod; } int main() { pow_[0]=1; for(int i=1;i<20;i++) pow_[i]=pow_[i-1]*10%Mod;//每一位的贡献预处理 scanf("%lld%lld%lld",&l,&r,&k); printf("%lld\n",(solve(r)-solve(l-1)+Mod)%Mod); return 0; }阅读更多
相关文章推荐
- Educational Codeforces Round 37 (Rated for Div. 2)F. SUM and REPLACE
- Educational Codeforces Round 40 (Rated for Div. 2) F. Runner's Problem 前缀和求区间覆盖 矩阵快速幂优化DP 离散化
- 【Educational Codeforces Round 53 (Rated for Div. 2)】
- Educational Codeforces Round 39 (Rated for Div. 2)D. Timetable(dp)
- Educational Codeforces Round 37 (Rated for Div. 2)-F-SUM and REPLACE(线段树)
- Educational Codeforces Round 37 (Rated for Div. 2) F. SUM and REPLACE(线段树)
- Educational Codeforces Round 37 (Rated for Div. 2) F. SUM and REPLACE(线段树,区间更新)
- Educational Codeforces Round 39 (Rated for Div. 2)(A-D)(水题 + 模拟 + 贪心模拟 + DP)
- 【Educational Codeforces Round 49 (Rated for Div. 2) 】
- Educational Codeforces Round 33 (Rated for Div. 2)
- Educational Codeforces Round 35 (Rated for Div. 2) F. Tree Destruction
- Educational Codeforces Round 39 (Rated for Div. 2) C. String Transformation
- 记一场(伪)CF (Educational Codeforces Round 40 (Rated for Div. 2) )
- codeforces Educational Codeforces Round 33 (Rated for Div. 2)B
- Educational Codeforces Round 39 (Rated for Div. 2) codeforces946 A.Partition B.Weird Subtraction Process C.String Transformation
- Educational Codeforces Round 39 (Rated for Div. 2) codeforces946 D. Timetable-数据处理+分组背包(处理炸裂)
- Educational Codeforces Round 34 (Rated for Div. 2) D - Almost Difference
- Educational Codeforces Round 46 (Rated for Div. 2) D. Yet Another Problem On a Subsequence
- Educational Codeforces Round 36 (Rated for Div. 2)C. Permute Digits(贪心)
- Educational Codeforces Round 37 (Rated for Div. 2)-E-Connected Components?(模拟/暴力)