Codeforces Global Round 4

题目链接:http://codeforces.com/contest/1178

A Prime Minister(贪心)

题意:Alice(下标为1)从n个数中选取数,每个数不能超过a[1]/2,选取数的总和超过sum/2,输出任意方案,无解输出0
题解:直接贪心取数即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=500010;//

int a[maxn];
vector<int> ve;
int n;
int main()
{
	while(~scanf("%d",&n)){
		int sum=0;
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);sum+=a[i];
		}
		ve.clear();
		ve.push_back(1);
		int cur=a[1];
		for(int i=2;i<=n;i++){
			if(cur*2>sum) break;
			if(a[i]*2<=a[1]){
				cur+=a[i];ve.push_back(i);
			}
		}
		if(cur*2<=sum){
			printf("0\n");
		}else{
			int len=ve.size();
			printf("%d\n",len);
			for(int i=0;i<len;i++){
				printf("%d%c",ve[i],i==len-1?'\n':' ');
			}
		}
	}
	return 0;
} 


B WOW Factor(简单dp)

题意:给一个v0串,问wow子串数,其中这里的w由两个连续的v组成。
题解:记录所有的v子串,扫一遍o的位置,每次加上left*(all-left)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1000010;//

char s[maxn];
vector<int> ve,ve2;
int len[maxn];
int main()
{
	while(~scanf("%s",s)){
		int n=strlen(s);
		ve.clear();
		memset(len,0,sizeof(len));//
		ll all=0;
		for(int i=0;i<n;i++){
			if(s[i]=='o') ve.push_back(i);
			else{
				int pos=i,cur=i;
				while((i+1)<n&&s[i+1]=='v'){
					pos=++i;
				}
				if(pos>cur){
					ve2.push_back(cur),len[cur]=pos-cur+1;
					all+=len[cur]-1;
				}
			}
		}
		ll left=0,ans=0;
		vector<int>::iterator cur=ve2.begin();
		for(auto i:ve){		
			while(cur<ve2.end()&&*cur<i){
				left+=len[*cur]-1;cur++;
			}

			ans+=left*(all-left);
		}
		printf("%I64d\n",ans);
	}
}

C Tiles

题意:给你wh的房间,需要wh个地板来填充,地板长这样,要求相邻地板邻接边颜色不同,问多少铺法
在这里插入图片描述
题解:固定第一块,有4种取法,再往右和往下填,都是2种,对于一个左边和右边都被填充的地板,其填充是固定的。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=998244353;
const int maxn=1000010;//


int main()
{
	int w,h;
	while(~scanf("%d%d",&w,&h)){
		ll ans=4;
		for(int i=1;i<w;i++) ans=ans*2%mod;
		for(int i=1;i<h;i++) ans=ans*2%mod;
		printf("%I64d\n",ans);
	}
	return 0;
}

D Prime Graph

参考:https://www.cnblogs.com/qieqiemin/p/11223610.html
题意:给你n,要求构造一个图,使得图边数是素数,且每个结点的度也是素数
题解:如果n是素数,那么我们直接连一个环即可;否则的话,利用一个结论,[n,n+n/2]必然存在一个素数,我们连完环后,从1开始,向它的对边连边,再从2开始继续这个过程,我们最多连n/2次,一定能找到一个素数,且每个结点的度数要么为2要么为3。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=998244353;
const int maxn=1010;//

bool isPrime[maxn+10];
int prime[maxn],pn;//

void getPrime()
{
	memset(isPrime,1,sizeof(isPrime));
	isPrime[0]=isPrime[1]=0;
	pn=0;
	for(long long i=2;i<maxn;i++)
	{
		if(isPrime[i])
		prime[pn++]=i;
		for(int j=0;j<pn&&prime[j]*i<maxn;j++)
		{
			isPrime[prime[j]*i]=0;
			if(i%prime[j]==0) break;
		}
	}
}
int main()
{
	getPrime();
	int n;
	while(~scanf("%d",&n)){
		if(isPrime[n]){
			printf("%d\n",n);
			for(int i=1;i<n;i++){
				printf("%d %d\n",i,i+1);
			}
			printf("%d %d\n",n,1);
		}else{
			int cur=n,ans=n;
			while(!isPrime[ans]) ans++;
			printf("%d\n",ans);
			for(int i=1;i<n;i++){
				printf("%d %d\n",i,i+1);
			}
			printf("%d %d\n",n,1);
			int id=1;
			while(!isPrime[cur]){
				cur++;
				printf("%d %d\n",id,id+n/2);
				id++;
			}
		}
	}
	return 0;
}

E Archaeology

参考:https://blog.csdn.net/starlet_kiss/article/details/97813132
题意:给一个由a b c构成的字符串,相邻位置的字符不同,要求构造长度不小于|s|/2的回文子串
题解:由于只有3个字符,且相邻位置的字符不同,4个字符中必然有2个相同,我们左右取字符即可。一开始wa了,参考了别人题解,才知道4个字符这个关键点。(tcl)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=998244353;
const int maxn=1000010;

bool vis[maxn];
char s[maxn];
int n;

int main()
{
	while(~scanf("%s",s)){
		memset(vis,0,sizeof(vis));
		n=strlen(s);
		if(n<=3){
			putchar(s[0]);puts("");continue;
		}
		int l=0,r=n-1;
		while(l<r){
			if(s[l]==s[r]) vis[l]=vis[r]=1;
			else if(s[l]==s[r-1]) vis[l]=vis[r-1]=1;
			else if(s[l+1]==s[r]) vis[l+1]=vis[r]=1;
			else vis[l+1]=vis[r-1]=1;
			l+=2;r-=2; 
		}
		for(int i=0;i<n;i++) if(vis[i]) putchar(s[i]);
		puts("");
	}
	return 0;
}

F1. Short Colorful Strip(区间DP)

代码&参考:https://www.cnblogs.com/Dup4/p/11220155.html#f1.-short-colorful-strip
题意:给定n和m(n==m)有n种颜色,把1到n位置的布分别染成ai种颜色,保证对于每种颜色在ai中都出现。问按颜色从小到大染色,有多少种染色方法。
题解:区间dp,找到当前区间最小颜色位置,对两边情况直接分开dp,再相乘。

F2 Long Colorful Strip (区间DP,好题)

代码参考:CF why112
题意:给定n和m,有n种颜色,把1到n位置的布分别染成ai种颜色,问按颜色从小到大染色,有多少种染色方法。
题解:很棒的区间DP,对于相邻的相同颜色,去重;DP时左边 * 中间 * 右边。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=510;
const int maxm=1000010;
const int mod=998244353;


int n,m;
int a[maxm];
struct node{
	int l,r,len;
	int a[maxn*2];
	
	void init(){
		l=r=len=0;
	}
	void insert(int x){
		a[len++]=x;
		if(len==1)
			l=r=x;
		else r=x;
	}
}s[maxn];
void Add(ll &x,ll y)
{
	x+=y;
	if(x>=mod) x-=mod;
}
ll dp[maxn*2][maxn*2];
ll dfs(int l,int r)
{
	//printf("l:%d r:%d \n",l,r);
	if(l>r) return 1;
	if(dp[l][r]!=-1) return dp[l][r];
	int pos=a[l];
	for(int i=l+1;i<=r;i++) if(a[i]<pos) pos=a[i];
	if(l==r){
		if(s[pos].l<l||s[pos].r>r) return dp[l][r]=0;
		else return dp[l][r]=1;
	}
	ll ans1=0,ans2=1,ans3=0;
	if(l==s[pos].l) ans1=1;else
	for(int i=l;i<=s[pos].l;i++){//注意i的取值,防止死循环、算漏,下同
		Add(ans1,dfs(l,i-1)*dfs(i,s[pos].l-1)%mod);
	}
	if(r==s[pos].r) ans3=1;else
	for(int i=s[pos].r;i<=r;i++){
		Add(ans3,dfs(s[pos].r+1,i)*dfs(i+1,r)%mod);
	}
	if(s[pos].len==1) ans2=1;else
	for(int i=0;i<s[pos].len-1;i++){
		ans2=ans2*dfs(s[pos].a[i]+1,s[pos].a[i+1]-1)%mod;
	}
	return dp[l][r]=ans1*ans2%mod*ans3%mod;
}
int main()
{
	while(~scanf("%d%d",&n,&m)){
		int i=1,x;
		for(int i=0;i<maxn;i++) s[i].init();
		for(int i=1;i<=m;i++){
			scanf("%d",&x);
			if(i>1&&x==a[i-1]){
				i--;m--;
			}else{
				a[i]=x;
				s[x].insert(i);
			}
		}
		if(m>=2*n){
			printf("0\n");continue;
		}
		memset(dp,-1,sizeof(dp));
		printf("%I64d\n",dfs(1,m));
	}
	return 0;
} 

G The Awesomest Vertex(分块、斜率优化、dfn序)

实在不会,,留坑吧
上粉兔巨巨代码:https://www.cnblogs.com/PinkRabbit/p/CF1178G.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值