下午学弟说第一题第二题只拿了一点分,于是过来看看题目。

P13549 热辣滚烫 - 洛谷https://www.luogu.com.cn/problem/P13549

判断字符串s1能否插入一个字符串变成s2,判断s1是否为s2的前缀或后缀。

int n,m;
string s1,s2,str;
bool a[N],b[N];
void solve(){
	cin>>n>>m;
	cin>>s1>>s2;
	if(n>m){
		cout<<"No\n";return;
	}
	memset(a,0,sizeof(a));memset(b,0,sizeof(b));
	a[0]=b[n]=1;
	for(int k=1;k<=n;k++){
		if(!a[k-1]) break;
		a[k]=(s1[k-1]==s2[k-1]);
	}
	for(int k=n-1;k>=0;k--){
		if(b[k+1]&&(s1[k]==s2[m-n+k])){
			b[k]=1;
		}
	}
	bool flag=0;
	for(int k=0;k<=n;k++){
		if(a[k]&&b[k]){
			flag=1;break;
		}
	}
	if(flag) cout<<"Yes\n";
	else cout<<"No\n";
}

P13551 ももいろの鍵 - 洛谷https://www.luogu.com.cn/problem/P13551

这是一道构造题。

我们先考虑特殊情况 n 为 2的幂次方-1,即 n 的二进制表达为全1如 。

在这种情况下,划分组数最大的方案是什么?

是不是每组两个数每位都相反,此时划分组数最大并且值为 。

例如 ,此时划分组为

这样划分组数最大,我们假设 m为 ,即m为最小大于n且全1的。

对于此时特殊情况 m=n。

需要满足上述构造,知道 i 则对应另一个数为 ,异或上全1则会翻转。


接下来扩展到所有情况

我们照例可以通过 n 求出全1的数 m,再循环判断即可。

如果n不是2的幂减一,必定会 0~n的尾部全部去掉,剩余前面 0~x。(与首尾相加求和一个道理,会从中间开始)

递归再次处理 0~x,直到最后所有数处理完毕。

vector<vector<int>> vt;
void check(int n) {
	if (n < 0) return;
	if (n == 0) {
		vt.push_back({0});
		return;
	}
	int k = log2(n);
	int m = (1 << (k + 1)) - 1;
	for (int i = 0; i <= (m+1)/2; i++) {
		int j = m ^ i;
		if (j > n || i >= j) continue;
		vt.push_back({i, j});
	}
	int L=(n^m)-1;
	check(L);
}
void solve(){
	int n;cin >> n;
	vt.clear();
	check(n);
	cout << vt.size() << "\n";
	for (auto &g : vt) {
		cout << g.size();
		for (int x : g)	cout << " " << x;
		cout << "\n";
	}
}

看完点个赞