C - 4-adjacent
Time limit : 2sec / Memory limit : 256MB
Problem Statement
We have a sequence of length N, a=(a1,a2,…,aN). Each ai is a positive integer.
Snuke's objective is to permute the element in a so that the following condition is satisfied:
For each 1≤i≤N−1, the product of ai and ai+1 is a multiple of 4.
Determine whether Snuke can achieve his objective.
Constraints
2≤N≤105
ai is an integer.
1≤ai≤109
Input
Input is given from Standard Input in the following format:
N
a1 a2 … aN
Output
If Snuke can achieve his objective, print Yes; otherwise, print No.
Sample Input 1
Copy
3
1 10 100
Sample Output 1
Copy
Yes
One solution is (1,100,10).
题意
给你一个长度为n的序列,然后让你重排列,使得任意相邻的两个数相乘都是4的倍数
题解
4 = 2^2,那么我们把所有数分为奇数,偶数,4的倍数三种,最后的排列,我们贪心一下可以发现,只要所有偶数全部放在一起,然后奇数和4的倍数交叉放就行。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int flag[maxn];
int a[maxn];
int n;
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
cin>>a[i];
if(a[i]%4==0){
flag[2]++;
}else if(a[i]%2==0){
flag[1]++;
}else{
flag[0]++;
}
}
if(flag[1])flag[0]++;
if(flag[0]-1>flag[2]){
cout<<"No"<<endl;
}else{
cout<<"Yes"<<endl;
}
}
D - Grid Coloring
Time limit : 2sec / Memory limit : 256MB
Problem Statement
We have a grid with H rows and W columns of squares. Snuke is painting these squares in colors 1, 2, …, N. Here, the following conditions should be satisfied:
For each i (1≤i≤N), there are exactly ai squares painted in Color i. Here, a1+a2+…+aN=HW.
For each i (1≤i≤N), the squares painted in Color i are 4-connected. That is, every square painted in Color i can be reached from every square painted in Color i by repeatedly traveling to a horizontally or vertically adjacent square painted in Color i.
Find a way to paint the squares so that the conditions are satisfied. It can be shown that a solution always exists.
Constraints
1≤H,W≤100
1≤N≤HW
ai≥1
a1+a2+…+aN=HW
Input
Input is given from Standard Input in the following format:
H W
N
a1 a2 … aN
Output
Print one way to paint the squares that satisfies the conditions. Output in the following format:
c11 … c1W
:
cH1 … cHW
Here, cij is the color of the square at the i-th row from the top and j-th column from the left.
Sample Input 1
2 2
3
2 1 1
Sample Output 1
1 1
2 3
Below is an example of an invalid solution:
1 2
3 1
This is because the squares painted in Color 1 are not 4-connected.
题意
给你ai表示第i个数有ai个,然后让你摆在一个HW的方阵里面,需要满足同一个数需要四联通放在一起。
题解
这个题目换个意思理解就是蛇形填数
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 105;
int mp[maxn][maxn];
int n,w,h,x,a[100005];
int main(){
scanf("%d%d",&h,&w);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
x=1;
for(int i=1;i<=h;i++){
if(i%2==1){
for(int j=1;j<=w;j++){
if(a[x]){
mp[i][j]=x;
a[x]--;
}else{
while(a[x]==0)x++;
mp[i][j]=x;
a[x]--;
}
}
}else{
for(int j=w;j>=1;j--){
if(a[x]){
mp[i][j]=x;
a[x]--;
}else{
while(a[x]==0)x++;
mp[i][j]=x;
a[x]--;
}
}
}
}
for(int i=1;i<=h;i++){
for(int j=1;j<=w;j++){
cout<<mp[i][j]<<" ";
}
cout<<endl;
}
}
E - Young Maids
Time limit : 2sec / Memory limit : 256MB
Problem Statement
Let N be a positive even number.
We have a permutation of (1,2,…,N), p=(p1,p2,…,pN). Snuke is constructing another permutation of (1,2,…,N), q, following the procedure below.
First, let q be an empty sequence. Then, perform the following operation until p becomes empty:
Select two adjacent elements in p, and call them x and y in order. Remove x and y from p (reducing the length of p by 2), and insert x and y, preserving the original order, at the beginning of q.
When p becomes empty, q will be a permutation of (1,2,…,N).
Find the lexicographically smallest permutation that can be obtained as q.
Constraints
N is an even number.
2≤N≤2×105
p is a permutation of (1,2,…,N).
Input
Input is given from Standard Input in the following format:
N
p1 p2 … pN
Output
Print the lexicographically smallest permutation, with spaces in between.
Sample Input 1
4
3 2 4 1
Sample Output 1
3 1 2 4
The solution above is obtained as follows:
p q
(3,2,4,1) ()
↓ ↓
(3,1) (2,4)
↓ ↓
() (3,1,2,4)
题意
给你一个长度为n的序列p,你每次需要抽出两个相邻的元素,然后把这两个数按照原来的顺序放在q的前面,直到p数组被抽完。
然后输出字典序最小解。
题解
倒着贪心,最后我们放在最前面的,就是最小的奇数加上最小的偶数。
然后我们放完这段之后,我们发现我们把原来的区间就会砍为三段,然后再在每一段找到最小的两个数即可。
不停的贪心下去就好了。
代码
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 2e5+7;
int n,a[maxn],log[maxn],f[2][18][maxn],pos[maxn];
int rmq(int k,int l,int r){
int j = log[r-l+1];
return min(f[k][j][l],f[k][j][r-(1<<j)+1]);
}
pair<int,int> cal(int l,int r){
int x = rmq(l&1,l,r);
int y = rmq((pos[x]+1)&1,pos[x]+1,r);
return {-x,-y};
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
pos[a[i]]=i;
}
for(int i=2;i<=n;i++){
log[i]=log[i>>1]+1;
}
for(int l=0;l<2;l++){
for(int i=0;i<n;i++){
f[l][0][i]=(i%2==l)?a[i]:1<<30;
}
for(int k=1;1<<k<=n;k++){
for(int j=0;j+(1<<k)-1<n;j++){
f[l][k][j]=min(f[l][k-1][j],f[l][k-1][j+(1 << k - 1)]);
}
}
}
priority_queue< pair<pair<int,int> ,pair<int,int> > > Q;
Q.push({cal(0,n-1),{0,n-1}});
while(!Q.empty()){
auto it = Q.top();Q.pop();
int x = -it.first.first;
int y = -it.first.second;
printf("%d %d ",x,y);
int l = it.second.first;
int r = it.second.second;
x = pos[x],y = pos[y];
if(l<x-1){
Q.push({cal(l,x-1),{l,x-1}});
}
if(x+1<y-1){
Q.push({cal(x+1,y-1),{x+1,y-1}});
}
if(y+1<r){
Q.push({cal(y+1,r),{y+1,r}});
}
}
}
F - Prime Flip
Time limit : 2sec / Memory limit : 256MB
Problem Statement
There are infinitely many cards, numbered 1, 2, 3, … Initially, Cards x1, x2, …, xN are face up, and the others are face down.
Snuke can perform the following operation repeatedly:
Select a prime p greater than or equal to 3. Then, select p consecutive cards and flip all of them.
Snuke's objective is to have all the cards face down. Find the minimum number of operations required to achieve the objective.
Constraints
1≤N≤100
1≤x1<x2<…<xN≤107
Input
Input is given from Standard Input in the following format:
N
x1 x2 … xN
Output
Print the minimum number of operations required to achieve the objective.
Sample Input 1
2
4 5
Sample Output 1
2
Below is one way to achieve the objective in two operations:
Select p=5 and flip Cards 1, 2, 3, 4 and 5.
Select p=3 and flip Cards 1, 2 and 3
题意
在1e7的范围,有n个位置为1,其他位置都是0.
每次你可以选择连续的奇数素数长度的数反转(0变1,1变0),问你最少多少次操作,可以使得全部变为0
题解
倒着异或,可以把题目转换为每次我可以选择两个间隔为奇数素数长度的数反转,然后最少多少次操作可以使得全部为0
然后显然就是二分图的最大匹配了。
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
using namespace std;
const int maxn = 2e5+7;
const int maxm = 1e7+7;
int n,a[maxm];
vector<int>v[2],E[maxn];
bool bio[maxn];
int conn[maxn];
void init(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
a[x]=1;
}
}
bool prime(int x){
if(x==1)return false;
for(int i=2;i*i<=x;i++)
if(x%i==0)return false;
return true;
}
bool dfs(int x){
if(bio[x])return false;
bio[x]=true;
for(auto it : E[x]){
if(conn[it] == -1 || dfs(conn[it])){
conn[it] = x;
return true;
}
}
return false;
}
int main(){
init();
memset(conn,-1,sizeof(conn));
for(int i=maxm-1;i;i--){
a[i]^=a[i-1];
if(a[i])v[i%2].push_back(i);
}
for(int i=0;i<v[0].size();i++){
for(int j=0;j<v[1].size();j++){
if(prime(abs(v[0][i]-v[1][j]))){
E[i].push_back(j);
}
}
}
int match = 0;
for(int i=0;i<v[0].size();i++){
memset(bio,false,sizeof(bio));
match+=dfs(i);
}
cout<<v[0].size()+v[1].size()-match+(v[0].size()-match)%2;
return 0;
}