问题描述
小俊很喜欢数学,现在他要给你出一道严肃的数学题。 定义 F[x] 为x在十进制表示下各位数字的异或和,例如F(1234) = 1 xor 2 xor 3 xor 4 = 4。给你两个数 a,b(a≤b)。 求F[a] + F[a+1] + F[a+2]+…+ F[b−2] + F[b−1] + F[b] 模 109+7 的值 。
输入描述
第一行一个T,表示有T组数据(T<26)。 每组数据第一行一个数a, 第二行一个数b,无多余空格。保证∣a∣,∣b∣不超过100001,∣a∣ 表示a的输入位数长度。
输出描述
按输入顺序输出。
第i组数据格式Case #i: ans
输入样例
4 0 1 2 2 1 10 9999 99999
输出样例
Case #1: 1 Case #2: 2 Case #3: 46 Case #4: 649032
dp[i][j]表示0到10的i次方中有多少个值为j的。ans[j]是表示从0到x中值为j的有多少个。
#include <cstdio> #include <cstring> #include <string> using namespace std; const int mod = 1e9 + 7; int dp[100020][20], ans[20]; char a[100020], b[100020]; int solve(char * str) { int ret = 0; int len = strlen(str); memset(ans, 0, sizeof(ans)); int pre = 0; for (int i = 0; i < len; i++) { int num = str[i] - '0'; for (int j = 0; j < num; j++) for (int k = 0; k <= 15; k++) { ans[pre ^ k ^ j] += dp[len - i - 1][k]; ans[pre ^ k ^ j] %= mod; } pre ^= num; } for (int i = 0; i <= 15; i++) ret = (ret + (long long)i * ans[i]) % mod; return ret; } int main() { int t; memset(dp, 0, sizeof(dp)); dp[0][0] = 1; for (int i = 0; i < 10; i++) dp[1][i] = 1; for (int i = 2; i < 100010; i++) for (int k = 0; k < 10; k++) for (int j = 0; j <= 15; j++) { dp[i][j ^ k] += dp[i - 1][j]; dp[i][j ^ k] %= mod; } scanf("%d", &t); int cas = 0; while (t--) { cas++; scanf("%s", a); scanf("%s", b); int len = strlen(b); int last = 0; for (int i = 0; i < len; i++) last ^= (b[i] - '0'); int ans = (solve(b) - solve(a) + mod) % mod; ans = (ans + last) % mod; printf("Case #%d: %d\n", cas, ans); } return 0; }