codeforces round 209 解题报告

ROUND 209 解题报告

A    Table

关键字:构造

思路:

    答案相当于是否存在一个边界上的格子值为1,且不是拐角。因为如果我们找到了这样一个点,我们可以将这个点,向对边两个点构成的两个矩形染色,这样就能在2的时间内完成。反之,不难证明,只能在4的时间内完成。

时间复杂度:O(nm)

空间复杂度:O(1)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>

using namespace std;
int n,m;
int num;
int main()
{
	cin>>n>>m;
	int flag=0;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
		{
			int x;
			cin>>x;
			if ((i!=1||i!=n)&&(j!=1||j!=m)&&x==1)
			{
				if (i==1||i==n||j==1||j==m) flag=1;
			}
		}
	if (flag) cout<<2<<endl;
	else cout<<4<<endl;
	return 0;
}


B    Permutation

关键字:构造

思路:

    我们首先考虑k0时的情况。只要我们在第一个sigma中的每个绝对值内正负情况相同,就能保证k=0 。这个不难构造,只要按12*n的顺序排列即可。考虑其他k的情况,如果k=1,我们交换和 2的位置,此时后面式子的值将会减二。如果k=2,那么在k=1的基础上,交换34的位置即可。。通过这种方式,我们就可以构造出要求的序列了。

时间复杂度:O(n)

空间复杂度:O(1)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>


using namespace std;


int main()
{
<span style="white-space: pre;">	</span>int n,k;
<span style="white-space: pre;">	</span>cin>>n>>k;
<span style="white-space: pre;">	</span>for (int i=1;i<=n;i++)
<span style="white-space: pre;">	</span>{
<span style="white-space: pre;">		</span>if (k>0) printf("%d %d",2*i,2*i-1);
<span style="white-space: pre;">		</span>else printf("%d %d",2*i-1,2*i);
<span style="white-space: pre;">		</span>if (i!=n) printf(" ");
<span style="white-space: pre;">		</span>k--;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>printf("\n");
<span style="white-space: pre;">	</span>return 0;
}


C    Prime Number

关键字:STL

思路:

    类似于进制的加法。我们所要求的结果,就是将ai序列的相同项不断合并,直至不能再合并时,x的(Σai-当前最大ai)次方的值。这里我们用一个map就可以轻松完成。从最大的ai开始往0遍历,如果当前值是x的倍数,那就将当前值除以x的值加到前一项中。直到不满足当前值是x的倍数这个条件时结束。

时间复杂度:O(n)

空间复杂度:O(n)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
typedef long long LL;
LL pow_mod(LL a,LL i,LL n)
{
	if (i==0) return 1%n;
	LL temp=pow_mod(a,i>>1,n);
    temp=temp*temp%n;
    if (i&1) temp=(LL) temp*a%n;
    return temp;
}
const LL mod=1e9+7;
LL n,x;
LL a[110000];
map<LL,LL> w;
int main()
{
	cin>>n>>x;
	LL sum=0;
	w.clear();
	for (int i=0;i<n;i++)
	{
		cin>>a[i];
		w[a[i]]++;
		sum+=a[i];
	}
	int i=a[n-1];
	while (w[i]%x==0)
	{
		w[i-1]+=w[i]/x;
		i--;
	}
	if (i<0) i=0;
	cout<<pow_mod(x,sum-i,mod)<<endl;
	return 0;
}


D    Pair of Numbers

关键字:暴力

思路:

    我们从j=1开始枚举aj的值。然后分别从两边扩展,直到当前数不是aj的倍数为止。这里加一个小优化就可以过:如果当前最右边扩展到r,那么下次jr+1开始,不影响程序的正确性。

时间复杂度:O(n)

空间复杂度:O(n)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>

using namespace std;
int a[400000],w[400000];
int main()
{
	int n;
	cin>>n;
	for (int i=0;i<n;i++)
		cin>>a[i];
	int maxx=0,num=0;
	for (int i=0;i<n;)
	{
		int r,l;
		r=l=i;
		while (l&&a[l-1]%a[i]==0) l--;
		while (r<n-1&&a[r+1]%a[i]==0) r++;
		i=r+1;
		r-=l;
		if (r>maxx) num=0,maxx=r;
	    if (r==maxx) w[num++]=l+1;
	}
	cout<<num<<" "<<maxx<<endl;
	for (int i=0;i<num;i++)
	{
		cout<<w[i];
		if (i!=n) printf(" ");
		else printf("\n");
	}
	return 0;
}


E    Neatness

关键字:构造

思路:

    题目只要求找出解,并没有要求最短,所以此题主要难点在于构造。我们可以用最“蠢”的方法,但是保证其最大的正确性:dfs。首先需要dfs(x0,y0)Dfs时,需要判断四个方向,是否有未遍历过且可达的点,我们再递归去遍历该点。另外一个策略就是,每每第一次到一个点时,将其灯打开,最后一次回到这个点时,将灯关闭,这样就保证了策略的正确性。

时间复杂度:O(n^2)

空间复杂度:O(n^2) 

 

 

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>

using namespace std;
int n,x,y;
int a[600][600],pp[600][600],sum=0;
char q[4000000];
int ans=0;
const int D[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
const char c[4]={'R','L','D','U'};
bool check(int x,int y,int d)
{
	for (x+=D[d][0],y+=D[d][1];x>=1&&x<=n&&y>=1&&y<=n;x+=D[d][0],y+=D[d][1])
		if (a[x][y]) return !pp[x][y];
	return 0;
}
void dfs(int x,int y)
{
	pp[x][y]=1;
	if (!a[x][y])
	{
		 a[x][y]=1;
		 sum++;
		 ans++;
		 q[ans]='1';
		}
	for (int i=0;i<4;i++) 
		if (check(x,y,i))
		{
			ans++;
			q[ans]=c[i];
			dfs(x+D[i][0],y+D[i][1]);
			ans++;
			q[ans]=c[i^1];
		}
	a[x][y]=0;
	sum--;
	ans++;
	q[ans]='2';
}
int main()
{
	cin>>n>>x>>y;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
		    scanf("%d",&a[i][j]),sum+=a[i][j];
	dfs(x,y);
	if (sum)
	{
		cout<<"NO"<<endl;
		return 0;
	}
	cout<<"YES"<<endl;
	for (int i=1;i<=ans;i++)
	    printf("%c",q[i]);
	cout<<endl;
	return 0;
}

 

 

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值