Codeforces Round #369 (Div. 2)

本文分享了一次比赛的经历,包括因未使用long long而导致的问题,以及通过合作完成比赛的感受。文章详细解析了三道题目(A、B、D)的算法实现过程,涉及座位查找、幻方验证及图定向计数等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

已经变成智障选手了。。。。好久没打比赛的后遗症。。。B题没开long long 被搞成SB。。不爽。。抱了SPS的大腿才上的分,感觉很不好。。。

A.
给一个公交车的座位图,X是有人坐,O是没人坐,问能不能找出一个并排的都没人坐的座位,可以的话就输出YES+答案(可以并排的座位用+号代替O),不行的话就输出NO
样例输入1:

6
OO|OX
XO|XX
OX|OO
XX|OX
OO|OO
OO|XX

样例输出1:

YES
++|OX
XO|XX
OX|OO
XX|OX
OO|OO
OO|XX

样例输入2:

4
XO|OX
XO|XX
OX|OX
XX|OX

样例输出2:

NO

就是暴力题嘛。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#define LiangJiaJun main
#define LL long long
#define pa pair<int,int>
using namespace std;
char mp[1004][14];
int n;
void print(){
	 for(int i=1;i<=n;i++){
		 for(int j=1;j<=5;j++)printf("%c",mp[i][j]);
		 printf("\n");
	 }
}
int LiangJiaJun(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%s",mp[i]+1);
	for(int i=1;i<=n;i++){
		if(mp[i][1]=='O'&&mp[i][2]=='O'){
			mp[i][1]=mp[i][2]='+';
			printf("YES\n");print();return 0;
		}
		if(mp[i][4]=='O'&&mp[i][5]=='O'){
			mp[i][4]=mp[i][5]='+';
			printf("YES\n");print();return 0;
		}
	}
	printf("NO\n");
	return 0;
}

B.
给一个残缺的幻方,上面有一个格子是0,求问在这个格子填上其他数字之后,能不能是一个幻方。能的话输出那个数字,不能的话输出-1
PS:填的数字要大于0 。。。

样例输入1:

3
4 0 2
3 5 7
8 1 6

样例输出1:

9

样例输入1:

4
1 1 1 1
1 1 0 1
1 1 2 1
1 1 1 1

样例输出:

-1

被这题坑惨了。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#define LiangJiaJun main
#define LL long long
#define pa pair<int,int>
using namespace std;
int n;
long long a[504][504],x,y,s,t,q;
int check(){
	if(a[x][y]<=0)return 0;

	for(int i=1;i<=n;i++){
		t=0;
		for(int j=1;j<=n;j++)
			t+=a[i][j];
		if(t!=s){
			return 0;
		}
	}
	for(int j=1;j<=n;j++){
		t=0;
		for(int i=1;i<=n;i++)
			t+=a[i][j];
		if(t!=s){
			return 0;
		}
	}
	t=0;
	for(int i=1;i<=n;i++)
		t+=a[i][i];
	if(t!=s) return 0;
	t=0;
	for(int i=1;i<=n;i++)
		t+=a[i][n-i+1];
	if(t!=s) return 0;
	return 1;
}
int LiangJiaJun(){
	scanf("%d",&n);
	if(n==1){
		cout<<"1";return 0;
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)scanf("%d",&a[i][j]);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(a[i][j]==0){x=i;y=j;}
	for(int i=1;i<=n;i++)
		if(i!=x){
			for(int j=1;j<=n;j++)
				s+=a[i][j];
			break;
		}
	for(int i=1;i<=n;i++)
		q+=a[x][i];
	a[x][y]=s-q;
	if(!check())cout<<"-1"<<endl;
	else cout<<a[x][y]<<endl;

	return 0;
}


D.
一个数字N,给定数组an,ai表示i到ai有连边,请问有多少种情况给所有的边定向,使得图中没有环。答案对10^9+7取模。

题解:按照给定的图,直接连i到a[i]的单向边,保证有且只有一个环(数据特征)。然后缩环,记下那个环的大小k(即环上的点数),答案就是(2k−2)∗(2n−k)(2^k-2)*(2^{n-k})(2k2)(2nk)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<stack>
#include<queue>
#define LiangJiaJun main
#define LL long long
#define pa pair<int,int>
#define MOD 1000000007LL
using namespace std;
struct edge{
    int to,next;
}e[1000004];
int h[300004],ne=0,cnt=0;
int n,r,p,a[300004],belong[300004],low[300004],dfn[300004],SCC;
int val[300004];
bool inq[300004];
stack<int>ST;
LL temp=0;
LL ans=1;
void insert(int u,int v){
     e[++ne].to = v;
     e[ne].next = h[u];
     h[u] = ne;
}
void tarjan(int x){
     inq[x] = 1;
     dfn[x] = low[x] = ++cnt;
     ST.push(x);
     for(int i=h[x];i;i=e[i].next){
        if(!dfn[e[i].to]){
            tarjan(e[i].to);
            low[x] = min(low[x],low[e[i].to]);
        }
        else if(inq[e[i].to]) low[x] = min(low[x],dfn[e[i].to]);
     }
     if(low[x] == dfn[x]){
        SCC++;int now = -1;
        while(now != x){
            now = ST.top();ST.pop();
            belong[now] = SCC;
            inq[now] = 0;
            val[SCC]++;
        }

     }
}

int LiangJiaJun(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int x;
		scanf("%d",&x);
		insert(i,x);
	}
	for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
	int rest=n;//cout<<SCC<<endl;
	for(int i=1;i<=SCC;i++){
		if(val[i]==1)continue;
		rest-=val[i];
		temp=1;
		for(int k=1;k<=val[i];k++)temp=(temp+temp)%MOD;
		temp=(temp-2LL+MOD)%MOD;
		ans=(ans*temp)%MOD;//cout<<ans<<endl;
	}
	temp=1;
	for(int k=1;k<=rest;k++)temp=(temp+temp)%MOD;
	ans=(ans*temp)%MOD;
	printf("%I64d\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值