HDU4507 吉哥系列故事——恨7不成妻(数位DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4507

题意:如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关:

  1、整数中某一位是7;
  2、整数的每一位加起来的和是7的整数倍;
  3、这个整数是7的整数倍;  

现在吉哥想知道在一定区间内[L,R]和7无关的数字的平方和。

思路:

HDU4507 吉哥系列故事——恨7不成妻(数位DP)

#include <iostream>

#include <cstdio>

#include <string.h>

#include <algorithm>

#include <cmath>

#include <vector>

#include <queue>

#include <set>

#include <stack>

#include <string>

#include <map>





#define max(x,y) ((x)>(y)?(x):(y))

#define min(x,y) ((x)<(y)?(x):(y))

#define abs(x) ((x)>=0?(x):-(x))

#define i64 long long

#define u32 unsigned int

#define u64 unsigned long long

#define clr(x,y) memset(x,y,sizeof(x))

#define CLR(x) x.clear()

#define ph(x) push(x)

#define pb(x) push_back(x)

#define Len(x) x.length()

#define SZ(x) x.size()

#define PI acos(-1.0)

#define sqr(x) ((x)*(x))

#define MP(x,y) make_pair(x,y)

#define EPS 1e-20



#define FOR0(i,x) for(i=0;i<x;i++)

#define FOR1(i,x) for(i=1;i<=x;i++)

#define FOR(i,a,b) for(i=a;i<=b;i++)

using namespace std;





void RD(int &x){scanf("%d",&x);}

void RD(i64 &x){scanf("%I64d",&x);}

void RD(u32 &x){scanf("%u",&x);}

void RD(double &x){scanf("%lf",&x);}

void RD(int &x,int &y){scanf("%d%d",&x,&y);}

void RD(i64 &x,i64 &y){scanf("%I64d%I64d",&x,&y);}

void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}

void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}

void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}

void RD(i64 &x,i64 &y,i64 &z){scanf("%I64d%I64d%I64d",&x,&y,&z);}

void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}

void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}

void RD(char &x){x=getchar();}

void RD(char *s){scanf("%s",s);}

void RD(string &s){cin>>s;}





void PR(int x) {printf("%d\n",x);}

void PR(i64 x) {printf("%I64d\n",x);}

void PR(u32 x) {printf("%u\n",x);}

void PR(double x) {printf("%.6lf\n",x);}

void PR(char x) {printf("%c\n",x);}

void PR(char *x) {printf("%s\n",x);}

void PR(string x) {cout<<x<<endl;}





const i64 mod=1000000007;

i64 f1[20][2][7][7],f2[20][2][7][7],f3[20][2][7][7];

i64 p[20],num[20];





void init()

{

    clr(f1,-1);

    clr(f2,-1);

    clr(f3,-1);

    int i;

    p[0]=1;

    for(i=1;i<20;i++) p[i]=p[i-1]*10%mod;

}





i64 mul(i64 x,i64 y)

{

    return (x%mod)*(y%mod)%mod;

}



i64 dfsCnt(int i,int x,int y,int z,int flag)

{

    if(i==-1) return x||!y||!z;

    if(!flag&&f1[i][x][y][z]!=-1) return f1[i][x][y][z];

    i64 ans=0,cnt;

    int d,u=flag?num[i]:9;

    for(d=0;d<=u;d++)

    {

        cnt=dfsCnt(i-1,x||d==7,(y+d)%7,(z*10+d)%7,flag&&d==u);

        ans=(ans+cnt)%mod;

    }

    if(!flag) return f1[i][x][y][z]=ans;

    return ans;

}



i64 dfsSum(int i,int x,int y,int z,int flag)

{

    if(i==-1) return 0;

    if(!flag&&f2[i][x][y][z]!=-1) return f2[i][x][y][z];

    i64 ans=0,temp,cnt;

    int d,u=flag?num[i]:9;

    for(d=0;d<=u;d++)

    {

        cnt=dfsCnt(i-1,x||d==7,(y+d)%7,(z*10+d)%7,flag&&d==u);

        temp=mul(d,p[i]);

        temp=mul(cnt,temp);

        ans=(ans+temp)%mod;

        temp=dfsSum(i-1,x||d==7,(y+d)%7,(z*10+d)%7,flag&&d==u);

        ans=(ans+temp)%mod;

    }

    if(!flag) return f2[i][x][y][z]=ans;

    return ans;

}



i64 dfs(int i,int x,int y,int z,int flag)

{

    if(i==-1) return 0;

    if(!flag&&f3[i][x][y][z]!=-1) return f3[i][x][y][z];

    i64 ans=0,temp,cnt,sum,_XX,_YY,_2XY;

    int d,u=flag?num[i]:9;

    for(d=0;d<=u;d++)

    {

        cnt=dfsCnt(i-1,x||d==7,(y+d)%7,(z*10+d)%7,flag&&d==u);

        sum=dfsSum(i-1,x||d==7,(y+d)%7,(z*10+d)%7,flag&&d==u);

        temp=mul(d,p[i]);

        _XX=mul(mul(temp,temp),cnt);

        _2XY=mul(2,mul(temp,sum));

        _YY=dfs(i-1,x||d==7,(y+d)%7,(z*10+d)%7,flag&&d==u);

        ans=(ans+_XX+_2XY+_YY)%mod;

    }

    if(!flag) return f3[i][x][y][z]=ans;

    return ans;

}





i64 cal(i64 x)

{

    i64 a=x,b=x+1,c=2*x+1;

    if(a%2==0) a/=2;

    else  b/=2;



    if(a%3==0) a/=3;

    else if(b%3==0) b/=3;

    else c/=3;



    return mul(a,mul(b,c));

}



i64 get(i64 x)

{

    if(!x) return 0;

    i64 temp=x,i=0,ans=cal(x);

    while(temp)

    {

        num[i++]=temp%10;

        temp/=10;

    }

    ans-=dfs(i-1,0,0,0,1);

    ans=(ans%mod+mod)%mod;

    return ans;

}



int main()

{

    init();

    int C;

    RD(C);

    while(C--)

    {

        i64 L,R;

        RD(L,R);

        i64 ans=get(R)-get(L-1);

        ans=(ans%mod+mod)%mod;

        PR(ans);

    }

    return 0;

}

  

 

你可能感兴趣的:(HDU)