vp总结 Codeforces Round 868 (Div. 2) sg函数经验++

 大概赛时达到86名,铭记新高。

ab题出的慢了,c题正常发挥,d出的比较快,是这场排名较高的原因

e赛后又学习了sg函数感觉赛时也能写。

还有提高空间。

这场劣势显然在读题上,还有对博弈论理解不清晰

优势在发现了题目数据范围的隐藏信息,快速推出规律

A

读题偏慢

B

读错题,联想到以前做过的题上了

C 找规律构造

找规律,从题目给定的定义入手,发现强合数规律

D 1900构造

思路:

        注意到题目数据范围限制k<=20,联想到字符数仅有26个

        观察样例,进一步理解题意

        列出字符串,找规律发现回文子串总是小于等于字符串长度

        猜测题目给定的数据范围是虚假的,不同回文子串数只能小于等于字符串长度

        粗略证明:

                如果一个字符串的所有字符都不同,那么不同回文子串数显然就是字符串长度

                如果出现一个相同的字符,那么减少了一个计数,如果想要增加一个计数,只能是这个字符到前一个字符形成回文串。

                到此时又有一个疑问,是否有可能这个相同的字符与多个相同的字符形成多种回文串从而多次增加计数,可举例说明

                如ababa,最后一个(1,5)与(3,5)都是回文串,但是(3,5)是与(1,3)相同的回文串,即已经被统计在第二个a的价值里的字符串,故一个位置最多增加一个计数(价值)

        在证明途中又自然发现,连续的相同字符,每个增加的计数都是1,如aaaa,价值是4。

        这显然是一种增加计数极为完美的方式,既简单又与之前k<=20相呼应。

        现在有了增加计数的方式,还需要考虑不计数的方式,即不增加回文串的方式,显而易见可以用abcabcabc的方式,此时再观察题目发现x与c都是从3开始的,意味着我们可以在字符串最前面先增加一个abc,接着再增加abc就不会在增加计数了。

        要注意一定要按顺序循环使用abc,wa1。

#include <bits/stdc++.h>
using namespace std;
#define int long long

int x[30];
int c[30];
 
void solve() {
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=k;i++)cin>>x[i];
	for(int i=1;i<=k;i++)cin>>c[i]; 
//	string tt="abc";
	string s="abc";
	int idx=4;
	int sum=3;
	int use=3;
	int go=0;
	int flag=1;
	for(int i=1;i<=k;i++){
		if(sum+x[i]-idx+1<c[i]){
			flag=0;
			break;
		}
		int need=c[i]-sum;
		for(int j=1;j<=need;j++){
			s+=(char)(use+'a');
		}
		int ext=sum+x[i]-idx+1-c[i];
		for(int j=1;j<=ext;j++){
			s+=(char)(go+'a');
			go++;
			go%=3;
		}
			
		if(need)use++;
		idx=x[i]+1;
		sum=c[i];
	}
	if(flag){
		cout<<"YES\n";
		cout<<s<<'\n';
	} else cout<<"NO\n";
	
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while (T--) {
        solve();
    }
    return 0;
}

E 2500博弈论 sg函数打表

最近刚好发现对sg函数理解不是很深刻,这场最大收获就是理解了sg函数

实际上理解了sg函数以后就很好做这道题了

        显然题目给定的是一个多个环的图。

        答案显然是这多个环的sg值异或起来。(以前对于这个异或的理解不是很深刻,看了下sg函数发现很巧妙)

        研究一个环的sg函数,一个环操作后变成一条链。

        而一条链操作后变成两条链。

        sg函数的分解就完成了。

        打表找到规律后直接用规律做题。

        感觉知道sg函数后这题的难度就骤降了。

#include <bits/stdc++.h>
using namespace std;
#define int long long

int n;
int l,r;
int dp[100][2];
int f[200010];
int cnt[200010];

int sg(int len,int f)
{
	if(dp[len][f]!=-1)return dp[len][f];
	if(len<l)return dp[len][f]=0;
	set<int>st;
	for(int i=l;i<=min(len,r);i++){
		if(f==1){
			st.insert(sg(len-i,0));
		} else {
			int len1=len-i;
			for(int j=0;j<=len1;j++){
				st.insert(sg(j,0)^sg(len1-j,0));
			}
		}
	}
	int ans=0;
	while(st.count(ans))ans++;
	return ans;
}

int find(int a)
{
	if(a==f[a])return a;
	return f[a]=find(f[a]);
}

void merge(int a,int b)
{
	int k1=find(a),k2=find(b);
	if(k1!=k2){
		f[k2]=k1;
		cnt[k1]+=cnt[k2]; 
	}
 } 
 
void solve() {
//	n=10;
//	l=3,r=5;
//	for(int i=1;i<=n;i++)
//		dp[i][0]=dp[i][1]=-1;
//    for(int i=1;i<=n;i++)
//    	cout<<sg(i,1)<<'\n';
	cin>>n>>l>>r;
	for(int i=1;i<=n;i++){
		cnt[i]=1;
		f[i]=i;
	}
	for(int i=1;i<=n;i++){
		int a,b;
		cin>>a>>b;
		merge(a,b);
	}
	int res=0;
	for(int i=1;i<=n;i++){
		if(find(i)==i){
//			cout<<cnt[i]<<endl;
			if(cnt[i]>=l&&cnt[i]<l+r)
				res^=cnt[i]/l;
		}
	}
	if(res)cout<<"Alice\n";
	else cout<<"Bob\n";
	
    
}

signed main() {
	ios::sync_with_stdio(false);
//	cin.tie(0),cout.tie(0);
    int T=1;
//    cin>>T;
    while (T--) {
        solve();
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值