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!