Codeforces Round #338 (Div. 2) ABCDE

来源:互联网 发布:本地网络波动怎么解决 编辑:程序博客网 时间:2024/06/07 17:18

A Bulbs

随便模拟下。

#include <bits/stdc++.h>using namespace std;#define ll long longbool vis [111];int main(){    int n,m;    cin>>n>>m;    for(int i=1;i<=n;i++){        int x;        cin>>x;        while(x--){            int y;            cin>>y;            vis[y]=1;        }    }    bool ok=1;    for(int i=1;i<=m;i++){        if(!vis[i])ok=0;    }    if(ok){        cout<<"YES"<<endl;    }else{        cout<<"NO"<<endl;    }    return 0;}

B Longtail Hedgehog

逆着dfs(大节点到小节点)转换为经典记忆化搜索问题,有向无环图的最长路。枚举找最值,注意溢出int。

#include <bits/stdc++.h>using namespace std;#define ll long longvector<int> adj[100010];int deg[100010];bool vis[100010];ll dp[100010];ll ans = 0;ll len = 0;int dfs(int u){    if(dp[u])return dp[u];    vis[u]=1;    int sz = adj[u].size();    int res = 1;    for(int i=0;i<sz;i++){        int v = adj[u][i];        if(v<u){            res = max(res,dfs(v)+1);        }    }    dp[u] = res;    return res;}int main(){    int n,m;    cin>>n>>m;    for(int i=1;i<=m;i++){        int u,v;        scanf("%d%d",&u,&v);        adj[u].push_back(v);        adj[v].push_back(u);        deg[u]++;        deg[v]++;    }    for(int i=1;i<=n;i++){        if(!vis[i])dfs(i);    }    for(int i=1;i<=n;i++){        ans = max(ans,deg[i]*dp[i]);    }    cout<<ans<<endl;    return 0;}

C Running Track

贪心,每次找最长匹配的段来使用。数据量小,匹配的时候暴力就可以。

#include <bits/stdc++.h>using namespace std;#define ll long longchar a[2222];char b[2222];char ra[2222];int lena,lenb;int match(char* str,int pb,int& enda){    int res = 0;    for(int s=0;s<lena;s++){        for(int i=0;i+s<lena;i++){            if(str[i+s]!=b[pb+i]){                break;            }else{                if(i+1>res){                    enda = i+s;                    res=i+1;                }            }        }    }    return res;}int main(){    scanf("%s",a);    scanf("%s",b);    lena = strlen(a);    lenb = strlen(b);    for(int i=0;i<lena;i++){        ra[i]=a[lena-1-i];    }    int pos = 0;    pair<int,int> ans[2222];    bool ok=1;    int cnt=0;    while(pos<lenb){        int end;        int endr;        int ma = match(a,pos,end);        int mra = match(ra,pos,endr);        if(ma+mra==0){            ok=0;            break;        }        if(ma>=mra){            ans[cnt++]=make_pair(end+2-ma,end+1);        }else{            ans[cnt++]=make_pair(lena+1-(endr+2-mra),lena+1-(endr+1));        }        pos+=max(ma,mra);    }    if(ok){        cout<<cnt<<endl;        for(int i=0;i<cnt;i++){            cout<<ans[i].first<<" "<<ans[i].second<<endl;        }    }else{        cout<<-1<<endl;    }    return 0;} 

D Multipliers

首先推公式。设有tot个不同的素数,分别是prime0~primetot1,每个素数分别出现了cnti次。考察第i个素数primei,它自己可以出现0~cnti次,而其他的素数共有cntcnti种组合。化简一下可以得到,该素数的贡献是prime(cnt)cnti/2i。也就是说需要先算出指数,然后用取模快速幂计算每个数的贡献。
注意指数可能很大,但是不能直接模1e9+7。根据费马小定理,指数可以对1e9+6取模,结果不变。还需要注意的是必须恰当处理除以2那个地方,具体见代码。

#include <bits/stdc++.h>using namespace std;#define ll long longconst ll mod = 1e9+7;ll quick_pow(ll base,ll n){    ll ans=1;    ll multi=base;    while(n){        if(n&1){            ans*=multi;            ans%=mod;        }        n>>=1;        multi*=multi;        multi%=mod;    }    return ans;}int p[200010];ll primes[200010];ll oriprimes[200010];ll cnt[200010];int tot = 0;int main(){    int n;    cin>>n;    ll ans = 1;    for(int i=1;i<=n;i++){        scanf("%d",&p[i]);        cnt[p[i]]++;    }    for(int i=1;i<=200000;i++){        if(cnt[i]){            primes[tot] = oriprimes[tot] = i;            cnt[tot] = cnt[i];            tot++;        }    }    ll product = 1;    int s = 0;    bool flag = 1;    for(int i=0;i<tot;i++){        product*=(cnt[i] + 1);        if(flag && (product&1) == 0){            product>>=1;            flag=0;        }        product%=(mod-1);    }    for(int i=0;i<tot;i++){             if(flag)cnt[i]>>=1;        ll tmp = cnt[i];        tmp *= product;        ll cur = quick_pow(primes[i],tmp);        ans *= cur;        ans%=mod;    }    cout<<ans<<endl;        return 0;}

E Hexagons

找规律。我的做法是先二分判断格子在第几圈,然后判断在哪条边上。其实也就是根据规律加加减减。

#include <bits/stdc++.h>using namespace std;#define ll long longll getR(ll x){    ll l = 0;    ll r = 666666666;    ll mid;    ll res = 0;    while(l<=r){        mid = (l+r)>>1;        ll sum = (6+6*mid)*mid/2;        if(sum>=x){            r = mid-1;        }else{            l = mid+1;            res = max(res,mid);        }    }    return res;}int main(){    ll n;    cin>>n;    if(n==0){        cout<<"0 0"<<endl;        return 0;    }    ll r = getR(n);    n-=(6+6*r)*r/2;    r++;    int dir = 0;    while(n>r){        n-=r;        dir++;    }    n--;    ll x,y;    switch(dir){        case 0:            x=r*2-1;            y=2;            y+=n*2;            x-=n;            break;        case 1:            x=r-2;            y=r*2;            x-=n*2;            break;        case 2:            x=-r-1;            y=r*2-2;            x-=n;            y-=n*2;            break;        case 3:            x=-r*2+1;            y=-2;            y-=n*2;            x+=n;            break;        case 4:            x=-r+2;            y=-r*2;            x+=n*2;            break;        case 5:            x=r+1;            y=-r*2+2;            x+=n;            y+=n*2;            break;    }    cout<<x<<" "<<y<<endl;    return 0;}
0 0