Codeforces Round #122 (Div. 2)

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove

A:判断一下3*n与K的关系就OK了,假设所有课都是3,如果还有分,那么随意安排,如果不够,则把部分课程变为2


B:k*(n+1)|(4*n)求出最小的k就行了,gcd(n+1,n)==1很明显,就看n+1里面有几个2因子就OK了


C:可以推出答案只有3种,-1,1,2

首先处理掉-1的情况,也就是初始只有0,1,2个#的情况

然后只需要枚举#,然后进行搜索,判断是否能够走到所有的点,就OK了

否则就是2

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<algorithm>
#define N 210005
#define inf 100000000
#define MOD 100000007
#define LL long long
#define mem(a,b) memset(a,b,sizeof(a))
#define Key_value ch[ch[root][1]][0]
#define _match(a,b) ((a)==(b))
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
int way[4][2]={0,1,0,-1,1,0,-1,0};
char str[55][55];
int flag[55][55],n,m;
bool check(){
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(str[i][j]=='#'&&flag[i][j]==0)
				return true;
	return false;
}
void dfs(int x,int y){
	flag[x][y]=1;
	for(int i=0;i<4;i++){
		int X=x+way[i][0],Y=y+way[i][1];
		if(X>=0&&X<n&&Y>=0&&Y<m&&!flag[X][Y]&&str[X][Y]=='#')
			dfs(X,Y);
	}
}
bool slove(){
	mem(flag,0);
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(str[i][j]=='#'){
				dfs(i,j);
				return check();
			}
}
int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		int cnt=0;
		for(int i=0;i<n;i++){
			scanf("%s",str[i]);
			for(int j=0;j<m;j++)
				if(str[i][j]=='#')
					cnt++;
		}
		if(cnt<3){printf("-1\n");continue;}
		bool ans=true;
		for(int i=0;i<n&&ans;i++)
			for(int j=0;j<m&&ans;j++)
				if(str[i][j]=='#'){
					str[i][j]='.';
					if(slove())
						ans=false;
					str[i][j]='#';
				}
		printf("%d\n",ans?2:1);
	}
	return 0;
}



D:搜索,每一步两种情况,这样的复杂度是2^30,不过可以注意到,其中有一种操作是异或,利用异或的性质,最多异或一次,两次及以上肯定不是最优的,加上这个剪枝就OK了

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<algorithm>
#define N 210005
#define inf 100000000
#define MOD 100000007
#define LL long long
#define mem(a,b) memset(a,b,sizeof(a))
#define Key_value ch[ch[root][1]][0]
#define _match(a,b) ((a)==(b))
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
int a[40][40],b[40],p[40],k[40];
int n,u,t;
LL ans;
void dfs(int dep,int two){
	LL tmp=0;
	for(int i=0;i<n;i++) tmp+=(LL)a[dep][i]*k[i];
	if((u-dep)%2==0)ans=max(ans,tmp);
	if(dep==u) return;
	for(int i=0;i<n;i++) a[dep+1][i]=a[dep][p[i]]+t;
	dfs(dep+1,0);
	if(two==1) return;
	for(int i=0;i<n;i++) a[dep+1][i]=(a[dep][i]^b[i]);
	dfs(dep+1,1);
}
int main(){
	while(scanf("%d%d%d",&n,&u,&t)!=EOF){
		for(int i=0;i<n;i++)scanf("%d",&a[0][i]);
		for(int i=0;i<n;i++)scanf("%d",&b[i]);
		for(int i=0;i<n;i++)scanf("%d",&k[i]);
		for(int i=0;i<n;i++)scanf("%d",&p[i]),p[i]--;
		ans=-(1ll<<60);
		dfs(0,0);
		printf("%I64d\n",ans);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值