1. 程式人生 > >Codeforces Round #467 (div.2)

Codeforces Round #467 (div.2)

return 個數 uniq IT 也不能 當前 sca 現在 ces

Codeforces Round #467 (div.2)

我才不會打這種比賽呢
(其實本來打算打的)
誰叫它推遲到了\(00:05\)
我愛睡覺

題解

A. Olympiad

翻譯

給你若幹人的成績
讓你劃定一個分數線
使得所有不低於這個分數線的人都可以獲獎
但是\(0\)分的人一定不能得獎
問你有多少種獲獎情況

題解

\(sort+unique\) 然後判斷一下最小值是不是\(0\)就行了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define ll long long #define RG register inline int read() { RG int x=0,t=1;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-'
)ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } int n,a[500]; int main() { n=read(); for(int i=1;i<=n;++i)a[i]=read(); sort(&a[1],&a[n+1]); int tot=unique(&a[1],&a[n+1
])-a-1; if(a[1]==0)tot--; printf("%d\n",tot); return 0; }

B. Vile Grasshoppers

翻譯

給定\(p,y\)
\(2..y\)內找到一個最大值\(x\)
使得\(x\)不能被\(2..p\)整除
無解輸出\(-1\)

題解

看到範圍這麽大。
真是嚇死人
首先考慮一下怎麽檢查一個值\(x\)是否可行
當然不需要枚舉\(2..p\)
最多只需要枚舉到\(\sqrt x\)

如果有解,要麽\(p\)很小,要麽\(y\)很大
很容易就可以枚舉出來
如果無解,\(p\)一定要很接近\(y\)
這樣不需要枚舉多少個數
復雜度\(O(???)\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
ll ans=0;
int main()
{
    int p,y;
    cin>>p>>y;
    for(int ans=y;ans>p;--ans)
    {
        bool fl=true;
        for(int i=2;i<=p&&i*i<=ans;++i)
            if(ans%i==0){fl=false;break;}
        if(fl){cout<<ans<<endl;return 0;}
    }
    puts("-1");
    return 0;
}

C. Save Energy!

翻譯

有一個人要煮雞吃
但是爐子每過\(k\)分鐘就會自動關上
這個人每過\(d\)分鐘會進廚房,如果爐子關上了他就會打開

爐子在打開的時候雞只需要\(t\)分鐘就可以煮熟
在關上的時候則需要\(2t\)分鐘
問這個人多久以後可以吃到雞

題解

這題很簡單啊
首先如果\(K\%d=0\)就不用考慮了
否則我們一定能夠找到一個最小的\(x\)
使得\(xd>K\)
這樣子的話,我們發現開關狀態以\(xd\)循環
接下來只要分類討論就行了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
ll K,d,t;
int main()
{
    cin>>K>>d>>t;t*=2;
    if(K%d==0){cout<<t/2<<endl;return 0;}
    ll st=K/d+1;
    ll T=st*d;
    ll ts=2*K+(T-K);
    double ans=t/ts*T;t%=ts;
    if(t<=2*K)ans+=t/2.0;
    else
    {
        ans+=K;
        t-=2*K;
        ans+=t;
    }
    printf("%.10lf\n",ans);
    return 0;
}

D. Sleepy Game

翻譯

有兩個人在玩一個遊戲
有一個棋子和有向圖
一開始棋子在某個位置
然後兩個人輪流走
誰先走不了誰就輸了
如果超過了\(10^6\)步則平局
但是現在第二個人睡覺去了
兩個人都由第一個人操控
問第一個人能不能贏,如果能輸出路徑
否則輸出平局或者必敗

題解

首先考慮能不能贏
因為能不能贏
只和到達一個出度為\(0\)的點的路徑的奇偶性有關
所以用一個\(BFS\)檢查能否以某個奇偶性到達某個點
如果有出度為\(0\)的點滿足條件,則輸出路徑

考慮平局,即能夠到達某個環
第一步檢查了能否到達
這樣找到環以後判斷一下就好
如果也不能平局,則必敗,輸出即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 120000
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
struct Line{int v,next;}e[MAX*2];
int h[MAX],cnt=1,n,m,H[MAX],B;
int dis[MAX][2],zy[MAX][2];
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
void outp(int now,int k,int w)
{
    if(!(k==now&&!w))outp(now,zy[k][w],w^1);
    printf("%d ",k);
}
bool bfs(int now)
{
    queue<pair<int,int> >Q;
    Q.push(make_pair(now,0));
    dis[now][0]=1;
    while(!Q.empty())
    {
        int u=Q.front().first,w=Q.front().second;Q.pop();
        for(int i=h[u];i;i=e[i].next)
        {
            int v=e[i].v;
            if(dis[v][w^1])continue;
            zy[v][w^1]=u;
            dis[v][w^1]=1;
            Q.push(make_pair(v,w^1));
        }
    }
    for(int i=1;i<=n;++i)
        if(!H[i]&&dis[i][1])
        {
            puts("Win");outp(now,i,1);puts("");
            return true;
        }
    return false;
}
int dfn[MAX],low[MAX],tim;
int S[MAX],top,G[MAX];
bool vis[MAX];
bool Ans;
void Tarjan(int u)
{
    S[++top]=u;vis[u]=true;
    dfn[u]=low[u]=++tim;
    for(int i=h[u];i;i=e[i].next)
    {
        int v=e[i].v;
        if(!dfn[v])Tarjan(v),low[u]=min(low[u],low[v]);
        else if(vis[v])low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u])
    {
        int v,size=0;
        do{v=S[top--];vis[v]=false;G[++size]=v;}while(u!=v);
        if(size!=1)
            for(int i=1;i<=size;++i)
                if(dis[G[i]][0]||dis[G[i]][1])Ans=true;
    }
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;++i)
    {
        H[i]=read();
        for(int j=1;j<=H[i];++j)Add(i,read());
    }
    B=read();
    if(bfs(B))return 0;
    for(int i=1;i<=n;++i)if(!dfn[i])Tarjan(i);
    if(Ans)puts("Draw");
    else puts("Lose");
    return 0;
}

E. Lock Puzzle

翻譯

給定一個串\(s\)和目標串\(s'\)

你每次都可以執行一個\(shift\)操作

執行\(shift(x)\)

假設原來的串是\(s=AB\)

那麽,現在的串變為了\(B^RA\)

其中,\(B\)的長度等於\(x\)

說白點,就是把後\(x\)個字符翻轉後,放在字符串的最前面

(舉個例子,原來是\(ababc\) ,執行\(shift(3)\)後,變為了\(cbaab\)

執行操作的次數不能超過\(6100\)

無解輸出\(-1\)

題解

我們假設前面已經匹配好了\(i-1\)

現在匹配第\(j\)

那麽,現在當前串中找到一個和目標位置相同的字符,位置是\(pos\)

然後考慮\(shift\)操作

當然,只需要執行\(shift(n-pos),shift(1),shift(n)\)三次操作就行了

我們假設當前串是\(AcB\)其中\(c=s[pos]\)

\(shift(n-pos)\)之後\(B^RAc\)

\(shift(1)\)之後\(cB^RA\)

\(shift(n)\)之後\(A^RBc\)

這樣的話,我們發現後面的位置就不會再變化了

而每次我們都把當前的目標字符給挪到了最後一個位置

這樣執行\(3n\)次操作之後就可以得到目標串了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 5000
int n,a[26],b[26];
char s[MAX],ss[MAX];
char s1[MAX],s2[MAX];
vector<int> ans;
void shift(char *s,int x)
{
    int t1=0,t2=0;
    for(int i=n-x+1;i<=n;++i)s2[++t2]=s[i];
    reverse(&s2[1],&s2[t2+1]);
    for(int i=1;i<=n-x;++i)s1[++t1]=s[i];
    for(int i=1;i<=x;++i)s[i]=s2[i];
    for(int i=1;i<=t1;++i)s[i+t2]=s1[i];
    ans.push_back(x);
}
int main()
{
    scanf("%d",&n);
    scanf("%s",s+1);
    scanf("%s",ss+1);
    for(int i=1;i<=n;++i)a[s[i]-97]++,b[ss[i]-97]++;
    for(int i=0;i<26;++i)if(a[i]!=b[i]){puts("-1");return 0;}
    for(int i=1;i<=n;++i)
    {
        int pos;
        for(int j=1;j<=n;++j)
            if(s[j]==ss[i]){pos=j;break;}
        shift(s,n-pos);shift(s,1);shift(s,n);
    }
    printf("%d\n",(int)(ans.size()));
    for(int i=0;i<ans.size();++i)
        printf("%d ",ans[i]);
    return 0;
}

Codeforces Round #467 (div.2)