250617 模拟赛

分数:\(88+15+8=111\)

出题人找了一个近年 noi 原题,然后我当时准备讲来着。发现 T1 T3 都是原。但是 T1 当时算了一下发现复杂度不对,开始绝望,九点(七点半开始)交了一下暴力。九点半左右比较的困出去晃了一圈回来发现复杂度算错了,然后发现正确的复杂度是正确的。然后写了一下正解发现被卡常了。然后开始卡常从 \(80\) 卡到 \(88\),感觉就差一个手写 bitset 之类的东西,但是不知道是懒还是什么没写。

\(10:10\) 左右获得了 \(80\) 分,然后在 \(11:01\)\(88\) 分了。然后开始写后面两个题暴力。T3 写了 \(15\) T2 写了 \(8\)


T1 现代量子力学引论

发现 \(k\le 15\) 非常奇怪,或许可以作为突破点。发现每一条信息可以分为 \(16\) 段长度为 \(16\) 的子段,根据鸽巢原理,如果一条信息是由一条信息没有经过坏人干扰生成的,它们至少有一个子段是完全相同的。所以考虑对于每一条信息,我们去找和它在每一个子段是相同的词库中的信息,然后一个一个检查是否存在符合要求的。

发现词库是随机生成的。所以说对于某一个位置的子段来说,每一种大概有 \(4\times 10^5/2^{16}\approx 7\) 个,所以对于每一条信息我们只需要检查最多概 \(7\times 16=112\) 条信息,如果用 bitset 维护信息(哎但是被卡常了,不如考虑手写)就非常快。luogu \(1.7s\) 可过。

点击查看代码
#include<cstdio>
#include<bitset>
#include<vector>
#define ull unsigned long long
#define id(i,j) ((j<<4)|i)
using std::bitset;
using std::vector;
inline ull read()
{
	ull t=0;char h=getchar();
	while(!isdigit(h))h=getchar();
	while(isdigit(h))t=(t<<1)+(t<<3)+(h^48),h=getchar();
	return t;
}
const int N=400000;
bitset<256>s[N+1];
ull myRand(ull&k1,ull&k2)
{
	ull k3=k1,k4=k2;
	k1=k4;k3^=(k3<<23);k2=k3^k4^(k3>>17)^(k4>>26);
	return k2+k4;
}
void gen(int n,ull a1,ull a2)
{
	for(int i=1;i<=n;i++)
        for(int j=0;j<256;j++)s[i][j]=(myRand(a1,a2)&(1ull<<32))?1:0;
}
int lk[16<<16],nxt[N*17],to[N*17],len=1;
inline void insert(int x,int y)
{
	to[++len]=y;nxt[len]=lk[x];lk[x]=len;
}
bitset<256>t;
int las=0,k;
short v[10];
int n,m;
ull a1,a2;
int u[20];
bool check()
{
	for(int l=16;~l;l--)
		for(int j=lk[id(l,u[l])];j;j=nxt[j])if((t^s[to[j]]).count()<=k)return true;
	return false;
}
short mp[100];
char h[100];
int x,now;
int main()
{
	freopen("qi.in","r",stdin);
	freopen("qi.out","w",stdout);

	for(int i='0';i<='9';i++)mp[i]=i-'0';for(int i='A';i<='F';i++)mp[i]=i-'A'+10;
	n=read();m=read();a1=read();a2=read();gen(n,a1,a2);
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<16;j++)
		{
			x=0;
			for(int k=0;k<16;k++)x<<=1,x|=s[i][(j<<4)|k];insert(id(j,x),i);
		}
	}
	while(m--)
	{
		scanf("%s",h);now=-1;k=read();
		for(int i=0;i<64;i++)
		{
			x=mp[h[i]];
			for(int j=0;j<4;j++)v[j]=x&1,x>>=1;
			for(int j=3;~j;j--)t[++now]=v[j]^las;
		}
		for(int j=0;j<16;j++)
		{
			x=0;
			for(int k=0;k<16;k++)x<<=1,x|=t[(j<<4)|k];
			u[j]=x;
		}
		las=check();
		puts(las?"1":"0");
	}
	return 0;
}

T2 战时全面情报网络

posted @ 2025-06-26 20:34  baiguifan  阅读(22)  评论(0)    收藏  举报