Codeforces Round #639 (Div. 2) 补题
Posted dinomax
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #639 (Div. 2) 补题相关的知识,希望对你有一定的参考价值。
A. Puzzle Pieces
首先只有一行或只有一列是可以拼出来的。之后可以猜出剩下的情况只有2x2可以,拼图只有一条边凹进去,构造过程中不难发现这一点。比较简单的写法是判断m+n>=mn
代码
#pragma GCC optimize(2)
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
#define INF 0x3f3f3f3f
#define x first
#define y second
typedef long long int ll;
using namespace std;
const int mod = 1000000007;
inline void read(int &p)
{
p=0;int flag=1;char c=getchar();
while(!isdigit(c)) {if(c==‘-‘) flag=-1;c=getchar();}
while(isdigit(c)) {p=p*10+c-‘0‘;c=getchar();}p*=flag;
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
if(n == 1 || m == 1) cout<<"YES
";
else if(n == 2 && m == 2) cout<<"YES
";
else cout<<"NO
";
}
return 0;
}
B. Card Constructions
我的做法是先写求出数列的通项,然后就能根据n得出不超过n的最大项数r,之后从r向下枚举,遇到n大于a[r]时,n就减去a[r],直到n变成0。
代码
#pragma GCC optimize(2)
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
#define INF 0x3f3f3f3f
typedef long long int ll;
using namespace std;
const int mod = 1000000007;
vector<int> a;
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int t;
cin>>t;
while(t--){
ll n;
cin>>n;
int ans = 0;
ll l=0,r=100000;
while(r-l>1){
ll mid=(l+r)/2;
if((3*mid*mid+mid)/2 > n) r=mid;
else l=mid;
}
for(ll i=l;;i--){
if(n<2) break;
ll p=(3*i*i+i)/2;
while(n>=p){
n -= p;
ans++;
}
}
cout<<ans<<endl;
}
return 0;
}
C. Hilbert‘s Hotel
这个题的题意花了好久才弄明白:旅馆里给每个非负整数都准备了一个房间,现在需要安排这些房间,有n个编号a[i],第k个整数安排到第k+a[k%n]个房间,问是不是会有两个数在一个房间。先考虑前k在[0,n-1]的情况,第i个数到房间i+a[i%n],那么第i+pn个数就会到房间pn+i+a[i%n],只要i+a[i%n]在模n的意义下互不相同,所有整数的安排就不会冲突。
代码
#pragma GCC optimize(2)
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
#define INF 0x3f3f3f3f
typedef long long int ll;
using namespace std;
const int mod = 1000000007;
inline void read(int &p)
{
p=0;int flag=1;char c=getchar();
while(!isdigit(c)) {if(c==‘-‘) flag=-1;c=getchar();}
while(isdigit(c)) {p=p*10+c-‘0‘;c=getchar();}p*=flag;
}
vector<int> a;
map<int, bool> vis;
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int t;
cin>>t;
while(t--){
int n;
cin >> n;
a.resize(n);
vis.clear();
for(auto &x:a) cin>>x;
bool flag = true;
for(int i=0;i<n;i++){
int p = i + a[i%n];
p = (p % n + n) % n;
if(!vis[p]){
vis[p] = 1;
}
else{
flag = false;
break;
}
}
if(flag) cout<<"YES
";
else cout<<"NO
";
}
return 0;
}
D. Monopole Magnets
我是先想到如果一个黑色区域可以通过放S满足题意,那么这个区域放满S也是可行的(可以画图试一下),这样只需要在这个黑色区域放一个N就可以,所以一个样例如果有解的话,答案就是图中黑色联通块的数量。之后考虑什么时候无解
1.因为每个黑色块里都有S,那么就不能存在某一行或某一列中存在两边是黑色中间是白色的情况,否则N就会从某一边的黑色沿着白色被吸到另一边的白色部分。
2.题中要求每一行每一列都要有S,如果某一行或某一列已经有黑块了,那么根据上面的构造就会有S。如果某一行没有黑块,但是图中每一列都有黑块,那么这一行就没法放S,否则这一行放S的那一列就会吸引同一列的黑色块中的N。
代码
#pragma GCC optimize(2)
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
#define INF 0x3f3f3f3f
typedef long long int ll;
using namespace std;
const int mod = 1000000007;
inline void read(int &p)
{
p=0;int flag=1;char c=getchar();
while(!isdigit(c)) {if(c==‘-‘) flag=-1;c=getchar();}
while(isdigit(c)) {p=p*10+c-‘0‘;c=getchar();}p*=flag;
}
int n,m;
int a[1005][1005];
bool vis[1005][1005];
bool r[1005], c[1005];
queue<int> q;
int ans;
int mx[4]={0,0,1,-1},my[4]={1,-1,0,0};
void bfs(int x, int y){
q = queue<int>();
q.push(x),q.push(y);
vis[x][y]=1;
while(!q.empty()){
int xx=q.front();
q.pop();
int yy=q.front();
q.pop();
for(int i=0;i<4;i++){
int tx = xx + mx[i];
int ty = yy + my[i];
if(vis[tx][ty]||!a[tx][ty]) continue;
if(xx<1||xx>n||yy<1||yy>m) continue;
vis[tx][ty]=1;
q.push(tx);
q.push(ty);
}
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char v;
cin>>v;
if(v==‘#‘) {
a[i][j] = 1;
r[i] = 1;
c[j] = 1;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(!vis[i][j]&&a[i][j]){
bfs(i, j);
ans++;//cout<<i<<" "<<j<<endl;
}
}
}
bool ok = true;
for(int i=1;i<=n;i++){
if(!r[i]){
int num = 0;
for(int j=1;j<=m;j++){
if(c[j]) num++;
}
if(num == m){
ok = false;
break;
}
}
}
if(!ok){
cout<<-1;
return 0;
}
for(int j=1;j<=m;j++){
if(!c[j]){
int num = 0;
for(int i=1;i<=n;i++){
if(r[i]) num++;
}
if(num == n){
ok = false;
break;
}
}
}
if(!ok){
cout<<-1;
return 0;
}
for(int i=1;i<=n;i++){
int num = 0;
for(int j=1;j<=m;j++) if(a[i][j]) num++;
int t = 0;
for(int j=1;j<=m;j++){
if(a[i][j]) t++;
else{
if(a[i][j-1]&&t<num){
ok = false;
break;
}
}
}
if(!ok) break;
}
if(!ok){
cout<<-1;
return 0;
}
for(int j=1;j<=m;j++){
int num = 0;
for(int i=1;i<=n;i++) if(a[i][j]) num++;
int t = 0;
for(int i=1;i<=m;i++){
if(a[i][j]) t++;
else{
if(a[i-1][j]&&t<num){
ok = false;
break;
}
}
}
if(!ok) break;
}
if(!ok){
cout<<-1;
return 0;
}
cout<<ans;
return 0;
}
以上是关于Codeforces Round #639 (Div. 2) 补题的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #639 (Div. 2) 补题
Codeforces Round #639 (Div. 2) 补题
Codeforces Round #639 (Div. 2)
Codeforces Round #639 (Div. 2)