好朋友(NC19367)数位

链接

Click here to see the original question

题目描述

BLUESKY007有很多关系很好的朋友,他们无一例外,名字均由数字组成(首字符不为0)且含有"007"(例如“10007”,“10707”就是她的好朋友,而“97037”,“70709”不是),即对于字符串s存在i,j,k(i< j< k)满足 s i s j s k ‾ = 007 ‾ \overline{s_is_js_k} = \overline{007} sisjsk=007

虽然BLUESKY007眼力极佳,一眼就能看出一个人是不是自己的好朋友,但BLUESKY007是个蒟蒻,她并不擅长数数,但她又想知道在[li,ri]内有多少人是自己的好朋友,所以就找到了你来帮忙.
她会向你询问t次,由于询问次数可能很多,所以你只需要告诉她t次询问答案的异或和即可.

输入

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

输出

一行一个整数表示答案

代码

#include 
using namespace std;
typedef long long int ll;
ll t, l, r, dp[30][20][2][2], ans;
int bit[30];//存储每一位的值
 
ll DFS(int pos, int legal0, bool before0, bool isMax, bool has007) {
    //pos:当前位数,legal0:合法的0的个数,出现在任意非0数后的0才算合法, before0:记录是否出现了非0数,isMax:当前是否达到了可能的最大值,has007:当前是否有了合法的007组合
    if(pos == 0) return has007;//能够到最后一步并且有了合法的007,说明合理
    if(!isMax && dp[pos][legal0][before0][has007]) return dp[pos][legal0][before0][has007];
    //已经计算过的数据就可以拿来重复利用
    ll cnt = 0;
    ll maxNum = isMax ? bit[pos] : 9;
    for(int i = 0; i <= maxNum; i++){
        cnt += DFS(pos - 1, legal0 + (before0 && i == 0), i || before0, isMax && i == maxNum, has007 || (legal0 >= 2 && i == 7));
    }
    return isMax ? cnt : dp[pos][legal0][before0][has007] = cnt;
    //未达到当前位数的最大值则将数据记忆下来
}
 
ll tran(ll num) {
    int pos = 0;
    while(num){
        bit[++pos] = num % 10;
        num /= 10;
    }
    return DFS(pos, 0, false, true, false);
}
 
int main() {
    cin>>t;
    ll ans = 0;
    while(t--){
      cin>>l>>r;
      ans ^= tran(r) - tran(l - 1);
    }
    cout<<ans<<endl;
    return 0;
}

如果您觉得我的文章对您有帮助的话,可以点个赞,点个关注,也可以扫描下方二维码关注我。我将在这个公众号上更新自己的学习笔记,以及分享一些算法知识

Study and progress together with me!

img

你可能感兴趣的:(Algorithm,算法,动态规划)