码迷,mamicode.com
首页 > 其他好文 > 详细

E. Segment Sum(数位dp)

时间:2019-03-27 20:58:57      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:记录   cstring   putc   pos   com   gcd   putchar   使用   ++   

技术图片

技术图片

题意:求一个区间内满足所有数位不同数字个数小于K的数字总和。比如:k=2   1,2,3所有数位的不同数字的个数为1满足,但是123数位上有三个不同的数字,即123不满足。

我们可以使用一个二进制的数字来记录某个数字是否已经出现,0为还没有出现,1表示该数字已经出现了。这里还需要注意前导零的干扰。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<stack>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
#define ri register int
typedef long long ll;

inline ll gcd(ll i,ll j){
	return j==0?i:gcd(j,i%j);
}
inline ll lcm(ll i,ll j){
	return i/gcd(i,j)*j;
}
inline void output(int x){
	if(x==0){putchar(48);return;}
	int len=0,dg[20];
	while(x>0){dg[++len]=x%10;x/=10;}
	for(int i=len;i>=1;i--)putchar(dg[i]+48);
}
inline void read(int &x){
    char ch=x=0;
    int f=1;
    while(!isdigit(ch)){
    	ch=getchar();
		if(ch==‘-‘){
			f=-1;
		}	
	}
    while(isdigit(ch))
        x=x*10+ch-‘0‘,ch=getchar();
        x=x*f;
}
struct st{
	ll num;
	ll sum;
	st():num(0),sum(0){
	}
	st(ll num,ll sum):num(num),sum(sum){
	}
}dp[20][2000];
int maxs; 
int a[20];
const ll mod=998244353;
int change(int n){
	int cnt=0;
	while(n){
		if(n&1)cnt++;
		n/=2;
	}
	return cnt;
}
st dfs(int pos,int sta,int pre,bool limit){
	if(pos==-1){
	//	cout<<pre<<endl;
	
		if(change(sta)<=maxs)
		return st(1,0);
		return st(0,0);
	}
	if(dp[pos][sta].num!=0&&!limit){
	//	printf("%d %lld\n",pos,dp[pos][sta].sum);
		return dp[pos][sta];
	}
	int up=limit?a[pos]:9; 
	st ans;	
	
	for(int i=0;i<=up;i++){
		st tem;
		if(change(sta|(int)pow(2,i))>maxs)
		continue;
		if(pre==0&&i==0){
			 tem=dfs(pos-1,sta,0,i==up&&limit);
		}
		else{
			tem=dfs(pos-1,((int)pow(2,i))|sta,i,i==up&&limit);
		}
		ans.num+=tem.num;
		ans.num=ans.num%mod;
	ans.sum=(ans.sum+(ll)pow(10,pos)%mod*i*tem.num%mod+tem.sum)%mod;
	}
	if(!limit){
		dp[pos][sta]=ans;
	}
	return ans;
}
ll solve(ll n){
	int len=0;
	while(n){
		a[len++]=n%10;
		n/=10;
	}
	return dfs(len-1,0,0,true).sum;
}
int main(){
	ll l,r;
	scanf("%lld%lld%d",&l,&r,&maxs);
	printf("%lld",(solve(r)-solve(l-1)+mod)%mod);
	return 0;
}

  

 

E. Segment Sum(数位dp)

标签:记录   cstring   putc   pos   com   gcd   putchar   使用   ++   

原文地址:https://www.cnblogs.com/Zhi-71/p/10610306.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!