hiho1033(数位dp)

这很明显就是数位dp好伐。。而且也不难啊。。

然后搞了半天。。真是越来越菜了qaq

直接统计当前累计的f函数值就可以,是加或减可以根据和最高位的位数差来判断了。。不过需要注意的是每个数的最高位数并不相同。。所以需要维护一下最高位数。。

另外这个题有个比较坑爹的地方就是很多方案是找不到符合题意的数的。。。所以dp过程中很多d都是0.。所以要判断一下当前状态是否找过了。。用d==0这个来判断真的是有风险。。。




/**
 *        ┏┓    ┏┓
 *        ┏┛┗━━━━━━━┛┗━━━┓
 *        ┃       ┃  
 *        ┃   ━    ┃
 *        ┃ >   < ┃
 *        ┃       ┃
 *        ┃... ⌒ ...  ┃
 *        ┃       ┃
 *        ┗━┓   ┏━┛
 *          ┃   ┃ Code is far away from bug with the animal protecting          
 *          ┃   ┃   神兽保佑,代码无bug
 *          ┃   ┃           
 *          ┃   ┃        
 *          ┃   ┃
 *          ┃   ┃           
 *          ┃   ┗━━━┓
 *          ┃       ┣┓
 *          ┃       ┏┛
 *          ┗┓┓┏━┳┓┏┛
 *           ┃┫┫ ┃┫┫
 *           ┗┻┛ ┗┻┛
 */ 
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-12
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 25
#define nm 350
#define pi 3.1415926535897931
using namespace std;
const ll inf=1000000007;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}



int n,tot=163,_t,b[NM];
ll l,r,d[NM][nm][NM],c[NM][nm][NM],v[NM];
bool _v[NM][nm][NM];

ll dfs(int i,bool f,int t,int k){
	if(!i)return t==_t+tot;
	if(!f&&_v[i][t][k])return d[i][t][k];
	int m=f?b[i]:9;ll ans1=0,ans2=0;
	inc(j,0,m){
		ll tmp=dfs(i-1,f&&j==m,t+j*((k-i)%2?1:-1),j==0&&k==i+1?k-1:k);
		(ans1+=tmp)%=inf;
		ans2=(ans2+tmp*v[i]%inf*j%inf+c[i-1][t+j*((k-i)%2?1:-1)][(j==0&&k==i+1?k-1:k)])%inf;
	}
	_v[i][t][k]=true;
	c[i][t][k]=ans2;
	return d[i][t][k]=ans1;
}

ll solve(ll x){
	n=0;mem(c);mem(d);mem(_v);
	if(x<0)return 0;
	for(ll t=x;t;t/=10)b[++n]=t%10;
	v[1]=1;inc(i,2,n)v[i]=(v[i-1]*10)%inf;
	dfs(n,1,tot,n+1);
	return c[n][tot][n+1];
}

int main(){
	freopen("data.in","r",stdin);
	l=read();r=read();_t=read();
	return 0*printf("%lld\n",(inf+solve(r)-solve(l-1))%inf);
}





#1033 : 交错和

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义交错和函数:

f(x) = a0 - a1 + a2 - ... + ( - 1)n - 1an - 1

例如:

f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4

给定 l, r, k,求在 [l, r] 区间中,所有 f(x) = kx 的和,即:

1405402477702.png

输入

输入数据仅一行包含三个整数,l, r, k(0 ≤ l ≤ r ≤ 1018, |k| ≤ 100)。

输出

输出一行一个整数表示结果,考虑到答案可能很大,输出结果模 109 + 7

提示

对于样例 ,满足条件的数有 110 和 121,所以结果是 231 = 110 + 121。

更多样例:

Input
4344 3214567 3
Output
611668829
Input
404491953 1587197241 1
Output
323937411
Input
60296763086567224 193422344885593844 10
Output
608746132
Input
100 121 -1
Output
120



样例输入
100 121 0
样例输出
231

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值