【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了。
数位动态规划的想法可以借鉴一下。

posted @ 2016-09-25 08:52  hiweibolu  阅读(164)  评论(0编辑  收藏  举报