您的位置:首页 > 编程语言

hihocode #1033 : 交错和

2016-04-12 10:15 253 查看


#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(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


看其他人的思路多是dfs求解,不过我用的是非递归的方式,而是先求出不同位上不同交错和的结果,再根据给定的范围[l,r],求出ans(r+1)-ans(l),即为最后的结果。过程相对dfs比较复杂,所以写加调试花了一下午加晚上。。。,sum
[k+100],记录n位数交错和为k的结果,flagh
[k+100],保存的是对应的结果中包含的数的个数。其中用了二分法求两个数的相乘以防越界



#include <iostream>
#include<stdio.h>
typedef long long ll;
#define MOD 1000000007
using namespace std;
ll sumh[19][210]= {{0}},flagh[19][210]= {{0}};
ll multiply( ll a,ll b)
{
if(a==1)
return b%MOD;
else
{
ll des=0,ans=b%MOD;
while(a>0)
{
if(a%2>0)
des=(des+ans)%MOD;
ans=(ans+ans)%MOD;
a/=2;
}
return des;
}
}
void init()
{
int i,j;
for(i=0; i<10; i++ )
{
sumh[1][i+100]=i;
flagh[1][i+100]=1;
}
sumh[0][100]=0;
flagh[0][100]=1;
ll tig=10;
for(i=2; i<=18; i++)
{
for(j=1; j<=9; j++)
{
for(int g=1; g<i; g++)
{
int flag=(i-g)%2>0?-1:1;
ll ad1=(tig*j)%MOD;
for(int k=-(g/2+1)*9; k<=(g/2+1)*9; k++)
{
if(flagh[g][k+100]>0)
{
int j2=j+k*flag+100;
ll s2=multiply(flagh[g][k+100],ad1);
sumh[i][j2]=(s2+sumh[g][k+100]+ sumh[i][j2])%MOD;
flagh[i][j2]=(flagh[g][k+100]+flagh[i][j2])%MOD;
}
}
}
}
tig*=10;
}

}
int change(ll a,int *num)
{
int l=0;
while(a>0)
{
num[l++]=a%10;
a/=10;
}
return l;

}

ll countn(ll a,int k)
{
int num[20]= {0};
int l=change(a,num);
ll ans=0;

for(int i=l-1; i>=1; i--)
{
if(flagh[i][k+100]>0)
ans=(ans+sumh[i][k+100])%MOD;
}
ll tig=1;
for(int i=1; i<=l-1; i++)
{
tig*=10;
}
int ad=0;
ll jtig=0;
for(int i=l-1; i>=0; i--)
{
int flag=1;
if((l-1-i)%2)
flag=-1;
for(int j=0; j<num[i] ; j++)
{
if(j==0&&i<l-1||j>0)
{
int ad1 =ad+flag*j;
int k3=(k-ad1);
for(int g=i; g>=0; g--)
{
if(g>0||i==0)
{
int k2=k3;
if((l-g)%2==1)
k2=k2*-1;
k2=k2+100;
if(flagh[g][k2]>0)
{
ans=(ans+sumh[g][k2])%MOD;
ll s2=multiply(flagh[g][k2],jtig+j*tig);
ans=(ans+s2)%MOD;
}
}
}
}
}

ad =ad+flag*num[i];
jtig+=num[i]*tig;
tig/=10;
}

return ans;

}

int main()
{
ll a,b;
int k;
init();
scanf("%lld%lld%d",&a,&b,&k);
ll ansa=countn(a,k);//printf("%lld\n",ansa);
ll ansb=countn(b+1,k)+MOD;//printf("%lld\n",ansb);
printf("%lld\n",(ansb-ansa)%MOD);//test(b,k);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态规划 数dp 代码