Codeforces Round #534 (Div. 2)題解
Codeforces Round #534 (Div. 2)題解
A. Splitting into digits
題目大意
將一個數字分成幾部分,幾部分求和既是原數,問如何分可以使得分出來的各個數之間的差值盡可能小
解題思路
將n分成n個1相加即可
AC代碼
#include<cstring> #include<string> #include<iostream> #include<cstdio> using namespace std; int main() { int n; scanf("%d",&n); printf("%d\n",n); for(int i=1;i<=n;i++) { printf("1"); if(i==n) puts(""); else printf(" "); } }
B. Game with string
題目大意
給出一段字符串,相同且相鄰的字母可以消去,消去後被消除的相鄰字母的兩側的字符串重新連接在一起,如可以消除奇數次輸出"Yes",如可以消除偶數次輸出"No"
解題思路
讀取字符串後用棧對原字符串進行處理,遍歷字符串,如最新的一個字符與棧頂元素相同則彈出棧頂元素,否則將當前字符插入棧中,統計總過彈出了多少次,即是可以消除的次數
AC代碼
#include<cstring> #include<string> #include<iostream> #include<cstdio> #include<stack> #include<cstring> using namespace std; const int size=1e5+5; char s[size]; int main() { scanf("%s",s); int len=strlen(s); stack<char> sta; int cnt=0; for(int i=0;i<len;i++) { if(!sta.empty()) { char t=sta.top(); if(t==s[i]) { sta.pop(); cnt++; continue;} } sta.push(s[i]); } if(cnt%2) puts("Yes"); else puts("No"); }
C. Grid game
題目大意
給出一個4*4的方陣圖,和一串字符串字符串中有1和0兩種字符分別代表"1*2"與"2*1"牌子,0代表豎著的牌子,1代表橫著的牌子,當一行或者一列被填充滿了之後其上將會消去,問若要將字符串順序的牌子依次入這個方陣圖應當如何放置.
解題思路
第奇數個豎的總之先放在左上角(1,1)的位置,第奇數個橫的總是先放在右下角(4,3)位置,當出現第偶數個豎著的牌子則將其放在(3,1),則其就會與提前放置好的奇數個豎牌子消去,當出現第偶數個橫的牌子則將其放在(4,1),這樣就會與提前放置好的奇數個橫牌子消去
AC代碼
#include<cstring> #include<string> #include<iostream> #include<cstdio> #include<cstring> using namespace std; char s[1005]; int main() { scanf("%s",s); int len=strlen(s); int v=0,h=0; for(int i=0;i<len;i++) { if(s[i]==‘0‘) { if(v==0) printf("1 1\n"),v=1; else printf("3 1\n"),v=0; } else { if(h==0) printf("4 3\n"),h=1; else printf("4 1\n"),h=0; } } }
D. Game with modulo
題目大意
交互題.讓你猜一個數字,每次輸出x,y,系統會返回x當\(x\%a\ge y\%a\)當\(x\%a<y\%a\)會返回y,題目要求在60次詢問內,得出答案
解題思路
首先設定函數\(f(x)=x\%a\)其函數圖像為 連續的邊長為a的等腰直角三角形.現通過設定一個l=0,r=1,通過每次l=r,r=2*r觀察其是否有\(f(r)<f(l)\),若有則可以固定出\(f(x)\)的一個周期,再對這個區間進行二分即可
AC代碼
#include<iostream>
#include<string>
using namespace std;
bool check(int l,int r)
{
char c;
cout << "? " << l << " " << r << endl; cin >> c;
if(c==‘y‘) return true;
else return false;
}
int main()
{
string s;
while(cin>>s&&s=="start")
{
int x=0,y=1;
while(check(x,y))
{
x=y;
y*=2;
}
int l=x,r=y,ans=x+1;
while(l+1<r)
{
int mid=(l+r)/2;
if(check(l,mid))
{
l=mid;
ans=mid+1;
}else{
r=mid;
}
}
cout<<"! "<<ans<<endl;
fflush(stdout);
}
}
E. Johnny Solving
題目大意
給出一連通圖,其中不存在自環和重邊,其有n個節點m條邊,給出一個參數k,若存在長度大於等於\(\frac{n}{k}\)則輸出“PATH”,並將那條路輸出,若存在k個滿足周長不被3整除,且每個圓都存在一個只屬於這個圓的點則輸出“CYCLES”並將k個圓的組成輸出,如都不存在則輸出-1
解題思路
首先我們需要明確一點,即或是圓或是路,其必然存在一個.假設不存在路,則一條不行成環的路的最長長度為\(\frac{n}{k}-1\)即環的周長的最大值為\(\frac{n}{k}-1\),因此至少可以構成k個環,且每個環都可以持有一個獨一無二的點,且對於每個點而言其度至少未3,因此,其至少能有兩個後驅,假如有一個後驅再回到起點的長度不是三的倍數,則有一個解,若兩個均是3的倍數,則這兩個點之間的距離也會是3 的倍數,因此可以從原本的點出發,通過一個後驅到達另一個後驅則必有3的倍數+2則必然不被3整除.路總是很容易找到的,直接對圖進行暴力搜索即可,訪問過的點進行標記,而總是不訪問已經訪問過點點則可以保證不成環.對環進行搜索時,首先對每次開始搜索的點打上標記並且加入一個路徑vector中,因為環只能通過再次訪問一個已經訪問過的點得到,因此對每一個點的後驅進行遍歷,若存在未訪問的點則優先將點訪問全,如都已訪問全則選取兩個後驅,則按照上面說的判斷周長是否被3整除的思路判斷出是否存在周長不為3的倍數的環即可.完成後再進行回溯,將加入的點從vector中彈出即可.
AC代碼
By FlyWhite, contest: Codeforces Round #534 (Div. 2), problem: (E) Johnny Solving, Accepted, #
#include<vector>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int size=25e4;
vector<int> g[size];
bool vis[size];
vector<int> path;
int pre[size];
int cir;
bool find_path(int v,int sz)
{
vis[v]=1;
path.push_back(v);
if(path.size()>=sz) return true;
for(auto u:g[v])
{
if(!vis[u])
if(find_path(u,sz)) return true;
}
path.pop_back();
return false;
}
void dfs(int v,int f)
{
vis[v]=1;
pre[v]=path.size();
path.push_back(v);
int flag=0;
for(auto u:g[v])
{
if(!vis[u]) {flag=1;break;}
}
if(flag)
{
for(auto u:g[v])
{
if(!vis[u])
{
dfs(u,v);
}
}
}
else if(cir>0)
{
int fax=-1,fay=-1;
for(auto u:g[v])
{
if(u==f) continue;
if(fax==-1) fax=u;
else if(fay==-1)
{
fay=u;
break;
}
}
if(pre[fax]<pre[fay]) swap(fax,fay);
int ori=-1;
if((pre[v]-pre[fax])%3!=2) ori=fax;
if((pre[v]-pre[fay])%3!=2) ori=fay;
if(ori!=-1)
{
printf("%d\n",pre[v]-pre[ori]+1);
for(int i=pre[v];i>=pre[ori];i--)
{
printf("%d%c",path[i],i==pre[ori]?‘\n‘:‘ ‘);
}
}
else
{
printf("%d\n",pre[fax]-pre[fay]+2);
int point=pre[fax];
printf("%d ",v);
for(;point>=pre[fay];point--)
{
printf("%d%c",path[point],point==pre[fay]?‘\n‘:‘ ‘);
}
}
cir--;
}
path.pop_back();
}
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
int sz=n/k;
if(n%k) sz+=1;
if(find_path(1,sz))
{
printf("PATH\n");
printf("%d\n",path.size());
for(int i=0;i<path.size();i++)
{
printf("%d%c",path[i],i==path.size()-1?‘\n‘:‘ ‘);
}
return 0;
}
path.clear();
memset(vis,0,sizeof(vis));
printf("CYCLES\n");
cir=k;
dfs(1,0);
return 0;
}
Codeforces Round #534 (Div. 2)題解