TopCoder SRM 575

div.1

T1

题意

每一步可以对把当前数N,减去 N的任意一个非1,N的因子。谁先不能操作就算输。

思路

记A(i) 为当N=i时先手是否必胜,显然A(i)只依赖于A(1)~A(i-1),可以暴力DP(N<100),即可观察到规律。
结论:当且仅当N为偶数,且N != 2^(2*x+1)(x为任意非负整数)时,为先手必胜,否则为先手必败。

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

class TheNumberGameDivOne {
public:
    string find( long long n );
};
string TheNumberGameDivOne::find(long long n) {
	if(n%2==1||n==2) return "Brus";
	int x=0;
	while(n%2==0)
	{
		x++;
		n=n/2;
	}
	if(x%2==1&&n==1) return "Brus";
    return "John";
}
T2

题意

题意:给一个整数序列A,随机选取两个不同的位置swap K次,然后选取A的一个非零子序列B,求SUM(B[i])的期望。

div.2

T3

题意

题意:给你一个N*M的矩阵,矩阵上的空位用’.'表示,非空位’X’表示。用L型的东西放进矩阵里,问最多能放多少个。
每个L型的物体可以随意旋转90度。
物体之间不能相互覆盖。
不能覆盖那些已经有X的格子。
每个L型的转角必须是黑色的格子。
一个格子是黑色,它的定义为,i+j是偶数 。
L型为
00
0

思路

如果数据范围小的话,用当前列的去更新下一列的,当前列可能对应着不同的方格占据方案,那么利用位压缩去对应各种不同的占据情况,那么这就是一个DP。

#include <bits/stdc++.h>
using namespace std;
int d[100][100],vis[100][100],a[100][100],n,m;
string ch[][2] = {
    {".X",
    "XB"},
    {"X.",
    "BX"},
    {"BX",
    "X."},
    {"XB",
    ".X"}
};
class TheTilesDivTwo {
public:
    int find( vector <string> board );
};
int check(char s,int i,int j)
{
	if(s=='.') return 1;
	if(vis[i][j]+a[i][j]!=0) return 0;
	if(s=='B')
	{
		if((i+j)%2==0) return 1;
		else return 0;
	}
	return 1;
}
void dfs(int s,int y,int x,int cnt)
{
	int t,i,j,f;
	if(x==n-1)
	{
		t=0;
		for(i=0;i<n;i++)
			if(vis[i][y+1])
				t=t|(1<<i);
		d[t][y+1]=max(d[t][y+1],d[s][y]+cnt);
		return;
	}
	dfs(s,y,x+1,cnt);
	for(t=0;t<4;t++)
	{
		f=1;
		for(i=0;i<2;i++)
			for(j=0;j<2;j++)
				if(check(ch[t][i][j],x+i,y+j)==0) f=0;
		if(f==0) continue;
		for(i=0;i<2;i++)
			for(j=0;j<2;j++)
				if(ch[t][i][j]!='.') vis[x+i][y+j]=1;
		dfs(s,y,x+1,cnt+1);
		for(i=0;i<2;i++)
			for(j=0;j<2;j++)
				if(ch[t][i][j]!='.') vis[x+i][y+j]=0;
	}
}
int TheTilesDivTwo::find(vector <string> aa) {
	int i,j,k;
	n=aa.size();
	m=aa[0].size();
	memset(d,-1,sizeof(d));
	memset(vis,0,sizeof(vis));
	memset(a,0,sizeof(a));
	for(i=0;i<n;i++)
		for(j=0;j<m;j++)
			if(aa[i][j]=='X')
				a[i][j]=1;
	d[0][0]=0;
	for(j=0;j<m;j++)
		for(i=0;i<(1<<n);i++)
			if(d[i][j]!=-1)
			{
				memset(vis,0,sizeof(vis));
				for(k=0;k<n;k++)
					if(i&(1<<k)) vis[k][j]=1;
				dfs(i,j,0,0);
			}

	k=0;
	for(i=0;i<(1<<n);i++)
		k=max(k,d[i][m-1]);
	return k;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值