T702094 都因为你 (you) 赛后题解
题目传送门
虽然是 T3,其实是最简单的一道题,赛场上脑抽了
“你干”是什么鬼
思路
通过打表,发现在 \(n\ge 100\) 的部分永远是“你干”的
证明
一个数模 3 余 、1、2。对于一个 \(n\ge 100\) 的数,考虑其相邻的两位 \(a_i,a_{i+1}\):
- \(a_i+a_{i+1}\equiv 0 \pmod 3\),则 \(n\) 包含 3 的倍数,\(n\) 为“你干”;
- \(a_i\equiv 0 \pmod 3\ or\ a_{i+1}\equiv 0 \pmod 3\),则 \(n\) 包含 3 的倍数,\(n\) 为“你干”。
所以如果想令 \(n\) 不为“你干”,需每一位模 3 同余。
此时的相邻的 3 位为 3 的倍数,矛盾。综上,\(n\ge 100\) 时,\(n\) 均为“你干”。
做法
对于 L 到 R 的 \(1\le n\le 99\) 的部分,打表暴力或纯粹暴力拆位。(共 24 个不是“你干”)
对于 L 到 R 的 \(100\le n\) 的部分,所有数均为答案。
时间复杂度:\(O(24t+24T)\),大概率通过 \(t\le 10^4,T\le10^7\)。
可将纯粹打表改为前缀和表,时间复杂度:\(O(t+T)\),可以通过 \(t\le 10^4,T\le10^7\)。
但没必要,我纯粹打表过了
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
unsigned int seed;
int mod, L, R;
unsigned long long shift()
{
seed ^= seed << 13;
seed ^= seed >> 7;
seed ^= seed << 17;
return seed;
}
void read()
{
L = shift() % mod + 1, R = shift() % mod + 1;
if(L > R) swap(L, R);
}
int a[100] = {0, 1, 2, 4, 5, 7, 8, 11, 14, 17, 22, 25, 28, 41, 44, 47, 52, 55,
58, 71, 74, 77, 82, 85, 88}; //1~99的非“你干”数,可优化为前缀和表
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t, T;
cin >> t >> T >> seed >> mod;
while(t --)
{
cin >> L >> R;
int ans = R - L + 1;
for(int i = 1; i <= 24; i ++)
{
if(a[i] >= L && a[i] <= R) ans --;
}
cout << ans << endl;
}
int Ans = 0;
while(T --)
{
read();
int ans = R - L + 1;
for(int i = 1; i <= 24; i ++)
{
if(a[i] >= L && a[i] <= R) ans --;
}
Ans ^= ans;
}
cout << Ans;
return 0;
}
hello, I'm yuzihang, if you need to copy this, please quote this url: https://www.cnblogs.com/yuzihang/p/19273346

浙公网安备 33010602011771号