codeforces round 534 (div. 2)

传送门

A. Splitting into digits(水题)

题解

全部输出1即可

1
2
3
4
5
6
    int n;
cin>>n;
cout<<n<<endl;
for(int i=1;i<=n;i++)cout<<1<<" ";
return 0;
}

B.Game with string (模拟栈)

一个字符串,如果连续两个一样的字符就削去,有连环效应,问削去次数是奇数还是偶数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    stack<char>st;
cin>>s;
int len=s.size();
int num=0;
for(int i=0;i<len;i++){
if(st.empty()||st.top()!=s[i]){
st.push(s[i]);
}
else{
st.pop();
num++;
}
}
if(num&1)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}

C.Grid gam (傻逼娱乐题)

题意

给出一个4*4的矩阵 每次下来一个1×2或者2×1的矩形,连续一行一列都填满就削去,问你每次把矩形放哪可以保证所有的矩形都能放下

题解

没看懂题意觉得神奇,以为是俄罗斯方块一样,看懂就弱智题,原来是可以制定位置,那就直接把横的放第一排,竖的都放第二三排,这样保证绝对可以削去;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

using namespace std;
typedef long long ll;
#define pp pair<int,int>
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int (int a,int b){while(b){int t=a%b;a=b;b=t;}return a;}
int lcm(int a,int b){return a*b/gcd(a,b);}
int mp[16][16];
void finx(){
if(mp[1][1]==0)cout<<1<<" "<<1<<endl,mp[1][1]=1,mp[1][2]=1;
else cout<<1<<" "<<3<<endl,mp[1][3]=mp[1][4]=1;
}
void finy(){
for(int j=1;j<=4;j++){
if(mp[2][j]==0){
cout<<2<<" "<<j<<endl;
mp[2][j]=1;
mp[3][j]=1;
return;
}
}
}
void earse(){
if(mp[1][1]&&mp[1][3]){
for(int i=1;i<=4;i++){
mp[1][i]=0;
}
}
for(int i=1;i<=4;i++){
if(mp[2][i]==0)return;
}
for(int i=1;i<=4;i++){
mp[2][i]=mp[3][i]=0;
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
string s;
cin>>s;
int len=s.size();
for(int i=0;i<len;i++){
if(s[i]=='1'){
finx();
earse();
}
else{
finy();
earse();
}
}
return 0;
}

D.Game with modulo (二分交互题)

题意

系统有一个a,你每次给出一个x和y

如果x%a>y%a 系统回答”x”,否则回答“y”;(你需要在60次内找出a, a<=1e9)

题解

首先大二分找出x的大区间(如果一大一小两个数%a都返回y说明a不在区间内否则a就在现在的x和y中)

然后小二分 区间,每次限制mid 逼近答案; 因为1e9找出最多30次,小区间最多三十次,所以60次足以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

using namespace std;
typedef long long ll;
#define pp pair<int,int>
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int (int a,int b){while(b){int t=a%b;a=b;b=t;}return a;}
int lcm(int a,int b){return a*b/gcd(a,b);}
char ch;
bool input(){
cin>>ch;
if(ch=='y')return true;
else return false;
}
int x=0,y=1;
bool check(int a,int b){
cout<<"? "<<a<<" "<<b<<endl;

if(input())return true;
else return false;
}
void dfs(){
while(check(x,y)){
swap(x,y);
y=x*2;
}
int l=x,r=y;
while(l+1<r){
int mid=(l+r)/2;
if(check(l,mid)){
l=mid;
}
else r=mid;
}
cout<<"! "<<r<<endl;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
string s;
while(cin>>s){
if(s[0]=='e')break;
x=0,y=1;
if(!check(x,y)){
cout<<"! "<<1<<endl;continue;
}
x=1;y=2;
dfs();
}
return 0;
}

E.Johnny Solving( 鸽笼定理)

题意

给出一连通图,不存在自环和重复边,n个点,m条边 并且每个点的度数都大于等于3,给出k;

1:如果这个图满足存在一条路径的长度大于等于n/k就输出”path”并输出路径

2:或者如果这个图有K个长度大于3并且不是3的倍数的环就输出circles ,并且输出环上的点

3:如果都不满足就输出-1;

题解

首先第一个可以直接dfs找出一条路径判断 easy

那么第二个 首先根据鸽笼定理,如果不存在长度为n/k的路径。那么这个图至少有k个叶子结点。

那么有什么用呢, 可以知道对于一个叶子结点并且度大于等于三 可以知道这个叶子结点肯定至少和除了父亲结点之外的两个祖先结点连接,(也就是说每个叶子结点都会在至少两个环内)

于是我们就判断一个叶子结点是否一个长度不为3的环即可;

如果长度都为3呢,那么看图

QQ图片20190130200943.png)

这个图按照dfs路径是1-2-3-4-5-6-7-8-9 然后对于9这个叶子结点来说 有两个环 9-7-8 和9-8-7-6-5-4

这两个环长度为3的倍数,但是可以看出这两个环又构成了一个新环9-7-6-5-4 这个环的长度就为5 所以是不是很巧妙

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

using namespace std;
typedef long long ll;
#define pp pair<int,int>
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int (int a,int b){while(b){int t=a%b;a=b;b=t;}return a;}
int lcm(int a,int b){return a*b/gcd(a,b);}
vector<int> G[maxn];
vector<int> leaves;
int fa[maxn];
int dep[maxn];
int vis[maxn];
void dfs(int u){
vis[u]=1;
bool leaf=true;
for(auto v : G[u]){
if(vis[v])continue;
leaf=false;
fa[v]=u;
dep[v]=dep[u]+1;
dfs(v);
}
if(leaf)
leaves.push_back(u);
}
void print(int s,int t){
while(s!=t){
cout<<s<<" ";
s=fa[s];
}
cout<<t<<endl;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n,m,k;
cin>> n >> m >> k;
int x,y;
while(m--){
cin>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
dep[1]=1;
dfs(1);
int p=n/k;if(n%k)p++;
for(int i=1;i<=n;i++){
if(dep[i]>=p){
cout<<"PATH"<<endl;
cout<<dep[i]<<endl;
print(i,1);
return 0;
}
}
cout<<"CYCLES"<<endl;
for(auto u :leaves){
bool flag=false;
vector<int>pre;
for(auto v: G[u]){
if(v==fa[u])continue;
if((dep[u]-dep[v]+1)%3){
flag=true;
cout<<dep[u]-dep[v]+1<<endl;
print(u,v);
break;
}
else{
pre.push_back(v);
}
}
if(!flag){
if(dep[pre[0]]>dep[pre[1]])swap(pre[0],pre[1]);
cout<<dep[pre[1]]-dep[pre[0]]+2<<endl;
cout<<u<<" ";
print(pre[1],pre[0]);
}
k--;
if(k==0)return 0;
}
return 0;
}