hdu5435 數位dp(大數的處理)

life4711發表於2015-09-18

http://acm.hdu.edu.cn/showproblem.php?pid=5435

Problem Description
Xiao Jun likes math and he has a serious math question for you to finish.

Define F[x] to the xor sum of all digits of x under the decimal system,for example F(1234) = 1 xor 2 xor 3 xor 4 = 4.

Two numbers a,b(ab) are given,figure out the answer of F[a] + F[a+1] + F[a+2]++ F[b2] + F[b1] + F[b] doing a modulo 109+7.
 

Input
The first line of the input is a single integer T(T<26), indicating the number of testcases.

Then T testcases follow.In each testcase print three lines :

The first line contains one integers a.

The second line contains one integers b.
1|a|,|b|100001,|a| means the length of a.
 

Output
For each test case, output one line "Case #x: y", where x is the case number (starting from 1) and y is the answer.
 

Sample Input
4 0 1 2 2 1 10 9999 99999
 

Sample Output
Case #1: 1 Case #2: 2 Case #3: 46 Case #4: 649032
/**
hdu5435 數位dp(大數的處理)
題目大意:一個數字的值為它各個位上數字異或的結果,給定兩個數,問二者閉區間內有所有數字值得和為多少?
解題思路:我用的是記憶話搜尋的寫法,好像遞迴耗時比較多吧,比賽時過了,後來給判掉了,最後老是TLE。
           網上學的方法: dp[i][j][k]表示前i位數(k==0||k==1)異或值為j的數有多少個,k為0則表示到結尾了,1表示沒有到結尾
           最後注意分別取模會TLE,具體看程式碼怎麼實現的吧
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
const int maxn=100005;
const LL mod=1e9+7;

char s1[maxn],s2[maxn];
int bit[maxn];
LL dp[maxn][16][2];

LL solve(char *a)
{
    int n=strlen(a);
    for(int i=1; i<=n; i++)bit[i]=a[i-1]-'0';
    memset(dp,0,sizeof(dp));
    dp[0][0][0]=1;
    for(int i=0; i<n; i++)
    {
        int num=bit[i+1];
        for(int j=0; j<16; j++)
        {
            dp[i][j][0]%=mod;
            dp[i][j][1]%=mod;
            if(dp[i][j][0]>0)
            {
                dp[i+1][j^num][0]+=dp[i][j][0];
                for(int k=0; k<num; k++)
                {
                    dp[i+1][j^k][1]+=dp[i][j][0];
                }
            }
            if(dp[i][j][1]>0)
            {
                for(int k=0; k<=9; k++)
                {
                    dp[i+1][j^k][1]+=dp[i][j][1];
                }
            }
        }
    }
    LL ans=0;
    for(int i=1; i<=15; i++)
    {
        ans+=(dp[n][i][0]+dp[n][i][1])*(LL)i;
        ans%=mod;
    }
    ans%=mod;
    return ans;
}

int main()
{
    int T,tt=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s%s",s1,s2);
        int n=strlen(s1);
        LL ans=s1[0]-'0';
        for(int i=1; i<n; i++)
            ans^=(s1[i]-'0');
        printf("Case #%d: %I64d\n",++tt,(solve(s2)-solve(s1)+ans+mod)%mod);
    }
    return 0;
}


相關文章