hdu4507恨7不成妻(数位dp) 2013腾讯编程马拉松初赛第一场

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

Time Limit: 1000/500 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1154    Accepted Submission(s): 343


Problem 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
 

Source
2013腾讯编程马拉松初赛第一场(3月21日)
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   4812  4810  4809  4808  4807 
 

Statistic |  Submit |  Discuss | Note


最近在练习数位dp,觉得自己很水很菜,就这道题我做了三天!!

其实如果是求个数有多少,相信很多人都会做。。因为这就是很简单的数位dp

但是它加了求平方和。。如果你是在平时的基础上改一下就会错了。。

主要是求平方和:

(tem+B1)^2  + (tem+B2)^2 + (tem+B3)^2 + ……(tem+Bn)^2 = tem^2*n + 2*tem(B1+B2+……Bn) + (B1^2 +B2^2+……+Bn^2)

这里的意思是假如有一个数 9535425471    DFS到2时 那其实我们是想求以2开头的5位数满足

情况的平方和,所以tem就为20000,而Bi就是递归下去找和20000匹配且满足要求的平方和

就是上面这一条公式了

#include
#include
const __int64 MOD = 1e9+7; 
typedef struct node
{
    __int64 nn;
    __int64 sum,sqsum;
    int flag;
};
node dp[31][10][10][3];
__int64 l,r;
__int64 po[22];
int m[22];
void Init()
{
    int i,k,j,r;
    po[0] = 1;
    for(i=1;i<22;i++)
        po[i] = (10*po[i-1])%MOD;

    for(i=0;i<30;i++)
        for(j=0;j<10;j++)
            for(k=0;k<10;k++)
                for(r=0;r<3;r++)
                {
                    dp[i][j][k][r].nn = dp[i][j][k][r].sum = dp[i][j][k][r].sqsum =dp[i][j][k][r].flag=0; 
                }


}
int tran(__int64 p)
{
    memset(m,0,sizeof(m));
    int b = 1;
    while(p)
    {
        m[b++] = p%10;
        p = p/10;
    }
    return b-1;
}
node DFS(int len,int flag1,int f,int p,int doing)//flag1是否有7,f后面的数之和
{                                                     //p后面的数平方之和
    node kk;
    kk.flag = kk.nn = kk.sqsum = kk.sum = 0;
    if(len==0) 
    {
        if(!flag1 && f!=0 && p!=0)
        {
            kk.nn = 1;
            return kk;
        }
        else
            return kk;
    }
    if(!doing && dp[len][f][p][flag1].flag)
        return dp[len][f][p][flag1];
    int end = doing?m[len]:9;
    node var1,var2;
    var1.sum = var1.sqsum = var1.nn = var1.flag = 0;
    var2.sum = var2.sqsum = var2.nn = var2.flag = 0;
    for(int i=0;i<=end;i++)
    {
        var1 = DFS(len-1,i==7?1:flag1,(f+i)%7,(p*10+i)%7,doing&&(i==end));
        __int64 tem = (i*po[len-1])%MOD; 
        var2.nn = (var1.nn+var2.nn)%MOD;
        var2.sum = (tem*var1.nn%MOD+var1.sum+var2.sum)%MOD;
        var2.sqsum = ( ((tem*tem)%MOD*var1.nn)%MOD + (2*tem*var1.sum)%MOD + var1.sqsum +var2.sqsum )%MOD;


    }
    if(!doing) 
    {
        var2.flag = 1;
        dp[len][f][p][flag1] = var2;
    }

    return var2;
}
int main()
{
    int t;
    Init();
    scanf("%d",&t);
    while(t--)
    {       
        scanf("%I64d%I64d",&l,&r);
        __int64 ll = DFS(tran(l-1),0,0,0,1).sqsum;
        __int64 rr = DFS(tran(r),0,0,0,1).sqsum;
        printf("%I64d\n",(rr-ll+MOD)%MOD);

    }
    return 0;

}



你可能感兴趣的:(正规比赛试题,数位dp)