hdu 5435 A serious math problem

A serious math problem

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)

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(a≤b)\) are given,figure out the answer of \(F[a] + F[a+1] + F[a+2]+…+ F[b−2] + F[b−1] + F[b]\) doing a modulo \(10^9+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

Source

BestCoder Round #55 ($)

这就是数位dp。。。。又想起了当年我作为一个被毒害的小朋友去写windy数的恐惧(哪天再去做一遍233)
我们来简单说一下这道题的做法:
\(dp[i][j]\) 表示\(i\)位数,异或值为\(j\)的数的个数。\((e.g.\ 0-9\ 10 - 99\ 100 - 999\ ......)\)
表示这个转移很暴力~~(代码展示---)
然而数位dp和别的不同的是,dp其实只是你的预处理。。。。你可能还要计数。。。(蒟蒻表示计数比dp难)
需要我们做的操作是求出所有小于等于\(a\)的自然数的异或值的和。而我们预处理的是很多个区间的答案,所以我们还要统计一下。
我们需要把\(a\)这个数给拆成很多个区间。。。
举个栗子:
\(3122=(0~999)+(1000~1999) + (2000~2999) + (3000 ~ 3589)\)
\((3000~3122)=(3000~3099)+(3100~3122)\)
\((3100~3122)=(3100~3109) + (3110~3119) + (3120~3122)\)
按这种方法分解以后,我们就和计数啦~
(注意:代码中可以看出,我们传进去是\(a\),实际上返回的是\(a-1\)的答案,所以适当调整一下~)


#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005, mod = 1e9 + 7;
char a[maxn], b[maxn];
int dp[maxn][20], ans[20];
int cas, last, qwe;

inline void prepare()
{
	dp[0][0] = 1;
	for(int i = 0; i <= 9; ++i) dp[1][i] = 1;
	for(int i = 2; i < maxn; ++i)
		for(int j = 0; j < 10; ++j)
			for(int k = 0; k <= 15; ++k)
				dp[i][j ^ k] += dp[i - 1][k], dp[i][j ^ k] %= mod; 
}

inline int workk(char * str)
{
	int len = strlen(str + 1); int pre = 0; int ret = 0;
	memset(ans, 0, sizeof(ans));
	for(int i = 1; i <= len; ++i)
	{
		int num = str[i] - '0';
		for(int j = 0; j < num; ++j)
		{
			for(int k = 0; k <= 15; ++k)
			{
				ans[pre ^ j ^ k] += dp[len - i][k];
				ans[pre ^ j ^ k] %= mod;
			}
		}
		pre ^= num;
	}
	for(int i = 1; i <= 15; ++i)	ret = (ret + (long long)i * ans[i]) % mod;
	return ret; 
}

int main()
{
	prepare();
	int t; scanf("%d", &t);
	while(t--)
	{
		cas++; qwe = 0; last = 0;
		scanf("%s", a + 1); scanf("%s", b + 1); int p = strlen(b + 1);
		for (int i = 1; i <= p; i++)  last ^= (b[i] - '0'); 
		qwe = (workk(b) - workk(a) + mod) % mod;	
		qwe = (qwe + last) % mod;  
        printf("Case #%d: %d\n", cas, qwe);  	
	}
	return 0;
}

posted @ 2018-03-23 11:17  沛霖  阅读(200)  评论(0编辑  收藏  举报