HDU 4507 吉哥系列故事——恨7不成妻 数位dp

来源:互联网 发布:淘宝直跳弹簧刀 编辑:程序博客网 时间:2024/06/05 03:59

Title

吉哥系列故事——恨7不成妻

Description

单身!
  依然单身!
  吉哥依然单身!
  DS级码农吉哥依然单身!
  所以,他生平最恨情人节,不管是214还是77,他都讨厌!
  
  吉哥观察了214和77这两个数,发现:
  2+1+4=7
  7+7=7*2
  77=7*11
  最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数!

  什么样的数和7有关呢?

  如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关——
  1、整数中某一位是7;
  2、整数的每一位加起来的和是7的整数倍;
  3、这个整数是7的整数倍;

  现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。

Input

输入数据的第一行是case数T(1 <= T <= 50),然后接下来的T行表示T个case;每个case在一行内包含两个正整数L, R(1 <= L <= R <= 10^18)。

Output

请计算[L,R]中和7无关的数字的平方和,并将结果对10^9 + 7 求模后输出。

Sample Input

3
1 9
10 11
17 17

Sample Output

236
221
0

题解:
一道……很毒瘤的数位dp。
我们可以定义一个结构体,用cnt表示符合要求的个数,sum表示这些数的和,sqsum表示平方和。
cnt很简单,一个朴素的数位dp。
sum可以用cnt表示。
这个数就是10^pos*i+x x表示这个数的后面部分。
则平方和就应该加
(10^pos*i+x)^2=(10^pos*i)^2+2*(10^pos*i*x+x^2

但是现在后面有一堆数。
即sum=10^pos*i+x1+10^pos*2+x2+…+10^pos*i+xn
=10^pos*i*cnt+(x1+x2+…+xn)
//cnt表示数的数量,而后面的一坨表示这一位的下一位的和。
同理,sqsum=(10^pos*i)^2*cnt+2*10^pos*i*(x1+x2+…+xn)+(x1^2+x2^2+…+性能……2)

用u表示之后的位的答案。
ans.sum=(10^pos*i)*u.cnt+u.sum;
ans.sqsum=(10^pos*i)^2*u.cnt+2*10^pos*i*u.sum+u.sqsum;

取模有毒。
而且我踏马一开始还看错了模数。

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#define ll long longusing namespace std;const int N = 20;const int M = 10;const int MOD = 1e9+7;int t;int a[N];ll mpow[N];struct node{    ll cnt,sum,sqsum;    node() {cnt=-1;sum=sqsum=0;}    void unit(){        cnt=sum=sqsum=0;    }}dp[N][M][M];node dfs(int pos,int mod,int sum,bool zero,bool limit){    if(pos==-1){        node u;u.cnt=(mod&&sum);        u.sum=0,u.sqsum=0;        return u;    }    if(!zero&&!limit&&dp[pos][mod][sum].cnt!=-1)        return dp[pos][mod][sum];    int mx;if(limit) mx=a[pos];else mx=9;    node ans;ans.unit();    for(int i=0;i<=mx;i++){        if(i==7) continue;        node u=dfs(pos-1,(mod*10+i)%7,(sum+i)%7,zero&&i==0,limit&&i==mx);        ans.cnt=(ans.cnt+u.cnt)%MOD;        //ans.cnt%=MOD;        ll a=mpow[pos];        ans.sum+=(u.sum+((a*i)%MOD)*u.cnt%MOD)%MOD;        ans.sum%=MOD;        ans.sqsum+=(u.sqsum+((2*a*i)%MOD)*u.sum)%MOD;        ans.sqsum%=MOD;        ans.sqsum+=((u.cnt*a)%MOD*a%MOD*i*i%MOD);        ans.sqsum%=MOD;       /* ans.sum=((ans.sum+i*a%MOD)*u.cnt%MOD)%MOD;        ans.sum=(ans.sum+u.sum)%MOD;        ans.sqsum=(ans.sqsum+((a*i)%MOD*(a*i%MOD)*(u.cnt%MOD))%MOD);        ans.sqsum=(ans.sqsum+(2*a*i%MOD*u.sum)%MOD)%MOD;        ans.sqsum=(ans.sqsum+(u.sqsum%MOD))%MOD;*/    }    if(!limit&&!zero) dp[pos][mod][sum]=ans;    return ans;}ll l,r;ll getans(ll x){    int cnt=0;    while(x){        a[cnt++]=x%10;        x/=10;    }    return dfs(cnt-1,0,0,1,1).sqsum;}int main(){    mpow[0]=1;    for(int i=1;i<=18;i++) mpow[i]=(mpow[i-1]*10)%MOD;    scanf("%d",&t);    while(t--){      cin>>l>>r;      ll ans=getans(r);      ans-=getans(l-1);      cout<<(ans%MOD+MOD)%MOD<<endl;    }    return 0;}
阅读全文
0 0
原创粉丝点击