1. 程式人生 > >Codeforces Round #534 (Div. 2)題解

Codeforces Round #534 (Div. 2)題解

vector 固定 開始 pro 統計 print 答案 一行 end

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)題解