【JZOJ4799】【NOIP2016提高A组模拟9.24】我的快乐时代
题目描述
输入
一行,两个整数l,r 。
输出
一行,一个整数,表示第l 天到第r 天的愉悦值的和。
样例输入
64 89
样例输出
1818
数据范围
解法
可以参考数位动态规划的想法。
从个位开始,逐位把特殊值变为一般值。
然后分类讨论即可。
代码
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#define ll long long
#define ln(x,y) int(log(x)/log(y))
#define sqr(x) ((x)*(x))
using namespace std;
const char* fin="aP3.in";
const char* fout="aP3.out";
const int inf=0x7fffffff;
const int maxn=30,mo=1000000007;
ll n,m,i,j,k,ans1;
ll qpower(ll a,ll b,ll mo){
ll c=1;
while (b){
if (b&1) c=a*a%mo;
a=a*a%mo;
b>>=1;
}
return c;
}
ll niyuan(ll a){
return qpower(a,mo-2,mo);
}
ll pp(ll v){
ll c=1;
for (;v;v--) c*=10;
return c;
}
ll count1(ll v){
ll i,j,k,cnt=1,ans=0,tmp=0,tmd,l,o,b[maxn],c[maxn];
if (v==0) return 0;
b[0]=0;
for (;v;v/=10) b[++b[0]]=v%10;
cnt=1;
ans=0;
for (k=1;k<=b[0];k++){
ans=(ans+b[k]*b[b[0]-k+1])%mo;
c[k]=1;
}
bool bz=false;
for (i=1;i<=b[0];i++){
for (j=(i==b[0]?1:0);j<b[i];j++){
o=b[i];
b[i]=j;
tmp=1;
for (k=1;k<=b[0];k++){
if (k*2-1==b[0]) {
if (!bz) ans=(ans+sqr(b[k])*(cnt/c[k])%mo)%mo;
else ans=(ans+b[k]*(cnt/c[k])%mo)%mo;
}
else ans=(ans+b[k]*b[b[0]-k+1]*(cnt/(c[k]*c[b[0]-k+1]))%mo)%mo;
}
b[i]=o;
}
if (i*2-1==b[0]) {
b[i]=285;
bz=true;
}
else b[i]=45;
c[i]=10;
cnt*=10;
}
ans=(ans+count1(pp(b[0]-1)-1))%mo;
return ans;
}
int main(){
scanf("%lld%lld",&n,&m);
ans1=count1(m)-count1(n-1);
ans1=(ans1+mo)%mo;
printf("%lld",ans1);
return 0;
}
启发
梦魇一般的题目。
要往死里打,遇到不对的数据,分类讨论到对为止。
改着改着就AC了。
数位动态规划的想法可以借鉴一下。