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;
}
posted @ 2025-11-26 16:05  yuzihang  阅读(12)  评论(0)    收藏  举报