好朋友

题目描述 

BLUESKY007有很多关系很好的朋友,他们无一例外,名字均由数字组成(首字符不为0)且含有"007"(例如“10007”,“10707”就是她的好朋友,而“97037”,“70709”不是),即对于字符串s存在i,j,k(i< j< k)满足\overline{s_is_js_k}=\overline{007}sisjsk=007.
虽然BLUESKY007眼力极佳,一眼就能看出一个人是不是自己的好朋友,但BLUESKY007是个蒟蒻,她并不擅长数数,但她又想知道在[li,ri]内有多少人是自己的好朋友,所以就找到了你来帮忙.
她会向你询问t次,由于询问次数可能很多,所以你只需要告诉她t次询问答案的异或和即可.

输入描述:

第一行一个整数t,表示询问个数 
接下来t行,每行两个整数li,ri

输出描述:

一行一个整数表示答案

输入

3
1 1000
233 666
999 999

输出

0

说明

在0~1000范围内不存在与题目要求相符的含有“007”的数,所以三次询问的答案都是0

输入

3
10000 10086
2333 23333
6666 66666

输出

132

备注:

对于20%的数据,li≤ri≤103 
对于40%的数据,t≤50,li≤ri≤5·104
对于100%的数据,1≤t≤105,0≤li≤ri≤1018
#include<bits/stdc++.h>
using namespace std;
const int N = 20;
typedef long long LL;
LL dp[N][N][2][2], dim[N];
LL dfs(int pos, int zeros, bool ok, int f, int lim) {
    if (pos < 0) return f;
    if (!lim && ~dp[pos][zeros][ok][f]) return dp[pos][zeros][ok][f];
    int up = lim ? dim[pos] : 9;
    LL ret = 0;
    for (int i = 0; i <= up; i++) {
        ret += dfs(pos - 1, ok ? zeros + (i == 0) : 0, ok || i != 0, f || (zeros >= 2 && i == 7), lim && i == up);
    }
    if (!lim) dp[pos][zeros][ok][f] = ret;
    return ret;
}
LL solve(LL x) {
    int len = 0;
    memset(dp, -1, sizeof(dp));
    memset(dim, 0, sizeof(dim));
    while (x) {
        dim[len++] = x % 10;
        x /= 10;
    }
    return dfs(len - 1, 0, false, 0, 1);
}
LL ask() {
    LL l, r;
    scanf("%lld%lld", &l, &r);
    return solve(r) - solve(max(l - 1, 0LL));
}
int main() {
    int T; LL ret = 0;
    scanf("%d", &T);
    while (T--) ret ^= ask();
    printf("%lld\n", ret);
    return 0;
}
posted @ 2020-08-01 10:54  HighLights  阅读(205)  评论(0)    收藏  举报