2020 CCPC Wannafly Winter Camp Day2 解题报告

A


计算每个元音对所包含它的区间的贡献,把这些贡献相加除以所以的的区间就是答案。


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
    ll x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return f? -x:x;
}

const int N=1e6+7;

double sum[N],f[N];
char s[N];

int main(){
    scanf("%s",s+1);
    int len=strlen(s+1);
    for(int i=1;i<=len;i++){
        if(s[i]=='a'||s[i]=='e'||s[i]=='i'||s[i]=='o'||s[i]=='u'||s[i]=='y'){
            sum[i]=sum[i-1]+1;
        }else sum[i]=sum[i-1];
    }

    double Ans=0;
    int i;
    for(i=1;i<=len/2;i++){
        if(i==1) f[i]=sum[len];
        else f[i]=f[i-1]+sum[len-i+1]-sum[i-1];
        Ans+=f[i]/(double)i;
    }
    for(;i<=len;i++){
        f[i]=f[len-i+1];
        Ans+=f[i]/(double)i;
    }

    Ans/=1.0*((double)(1.0*len*(1.0*len+1.0))/2.0);

    printf("%.9lf\n",Ans);

}

B


由nim和的性质可知要把当前局面变成先手必败态,需要选定某一堆拿去一些石子。设当前亦或和为\(x\),相当于求有多少个\(y\)满足\(y>x\ xor\ y\),这样就能将y变为\(x^y\)来使得异或和为0。满足这样条件的\(y\)一定在是\(x\)最高为1的二进制位也是1的\(y\)


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
    ll x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return f? -x:x;
}

const int N=1e5+7;

int n;
ll a[N],x=0;
int cnt[67];

int main(){
    n=input();
    for(int i=1;i<=n;i++)
        a[i]=input();

    for(int i=1;i<=n;i++){
        for(int j=60;j>=0;j--){
            if(a[i]&(1ll<<j)) cnt[j]++;
        }
        x^=a[i];
        int res=0;
        for(int j=60;j>=0;j--){
            if(x&(1ll<<j)){
                res=cnt[j];
                break;
            }
        }
        printf("%d\n",res);
    }
}

E


树上启发式合并set。


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
    ll x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return f? -x:x;
}

#define pb push_back

const int N=1e5+7;

vector <int> G[N];
set <int> s[N];
ll Ans[N];

void dfs(int u,int fa){
    s[u].clear();s[u].insert(u);Ans[u]=0;
    for(auto v:G[u]){
        if(v==fa) continue;
        dfs(v,u);
        if(s[v].size()>s[u].size()) swap(s[v],s[u]),Ans[u]=Ans[v];
        for(auto &iter:s[v]){
            auto pos=s[u].lower_bound(iter);
            if(pos==s[u].end()){
                auto tmp=pos;--tmp;
                Ans[u]+=1ll*(iter-*tmp)*(iter-*tmp);
            }else if(pos==s[u].begin()){
                Ans[u]+=1ll*(iter-*pos)*(iter-*pos);
            }else{
                auto tmp=pos;--tmp;
                Ans[u]-=1ll*(*pos-*tmp)*(*pos-*tmp);
                Ans[u]+=1ll*(iter-*pos)*(iter-*pos);
                Ans[u]+=1ll*(iter-*tmp)*(iter-*tmp);
            }
            s[u].insert(iter);
        }
        s[v].clear();
    }
}

int main(){
    int n=input();
    for(int i=2;i<=n;i++){
        int v=input();
        G[i].pb(v);
        G[v].pb(i);
    }

    dfs(1,0);

    for(int i=1;i<=n;i++){
        printf("%lld\n",Ans[i]);
    }

}

K


DP,直接转移时间复杂度显然过不了,考虑再AC自动机上转移就减少为根号级别,就可以过了。


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
    ll x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return f? -x:x;
}

const int N=5e5+7;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n;

ll dp[N],val[N];

namespace AC{
    int tr[N][26],tot,dep[N];
    int fail[N];
    void Ins(char *s,ll w){
        int u=0;
        for(int i=1;s[i];i++){
            if(!tr[u][s[i]-'a'])tr[u][s[i]-'a']=++tot;
            u=tr[u][s[i]-'a'];
        }
        val[u]=min(val[u],w);
        dep[u]=strlen(s+1);
    }

    void build(){
        queue<int> q;
        for(int i=0;i<26;i++)
            if(tr[0][i]) q.push(tr[0][i]);
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=0;i<26;i++){
                if(tr[u][i])
                    fail[tr[u][i]]=tr[fail[u]][i],q.push(tr[u][i]);
                else tr[u][i]=tr[fail[u]][i];
            }
        }
    }

    void query(char *t){
        int u=0;
        for(int i=1;t[i];i++){
            u=tr[u][t[i]-'a'];
            for(int j=u;j;j=fail[j]){
                if(dep[j])
                    dp[i]=min(dp[i],dp[i-dep[j]]+val[j]);
            }
        }
        if(dp[strlen(t+1)]>=INF) printf("-1\n");
        else printf("%lld\n",dp[strlen(t+1)]);
    }
}
void init(){
    for(int i=0;i<N;i++)
        dp[i]=val[i]=INF;
    dp[0]=val[0]=0;
}

char s[N];
int main(){
    n=input();init();
    for(int i=1;i<=n;i++){
        ll w;
        scanf("%s%lld",s+1,&w);
        AC::Ins(s,w);
    }
    scanf("%s",s+1);
    AC::build();
    AC::query(s);
    return 0;
}

H


直接抄原题解:

考虑\(k\)个点的完全图,若\(k\)为奇数,则存在一条欧拉回路。若\(k\)为偶数,同理至少把\(k-2\)个点补足\(\frac{k-2}{2}\)条边,使得除\(2\)点外任意一点度数都为偶数才会存在欧拉路径。

因此,通过二分/小心枚举得到最大的\(m\),之后建图跑欧拉回路。


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
    ll x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return f? -x:x;
}

const int N=4e3+7;
int G[N][N],cur[N];
int Ans[N*N],cnt;
ll n,m;

void solve(){
    int x=1;cnt=0;
    while(x<=m){
        Ans[cnt++]=x;
        while(cur[x]<=m&&G[x][cur[x]]==0) cur[x]++;
        G[x][cur[x]]--;G[cur[x]][x]--;
        x=cur[x];
    }
}

int main(){
    n=input();
    ll l=1,r=3ll*sqrt(n)+1;
    while(l<r){
        ll mid=(l+r)/2,tmp=0;
        if(mid&1) tmp=mid*(mid-1)/2+1;
        else tmp=mid*mid/2;
        if(tmp>n) r=mid;
        else l=mid+1;
    }
    m=l-1;
    printf("%lld\n",m);
    if(n>2000000) return 0;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=m;j++) G[i][j]=i==j?0:1;
    }
    if(m%2&&m>1) G[1][m]--,G[m][1]--;
    else{
        for(int i=3;i<=m;i+=2)
            G[i][i-1]++,G[i-1][i]++;
    }
    for(int i=1;i<=m;i++) cur[i]=1;
    solve();
    while(cnt<n) Ans[cnt++]=1;
    for(int i=0;i<cnt;i++){
        printf("%d%c",Ans[i],i==cnt-1? '\n':' ');
    }
}

猜你喜欢

转载自www.cnblogs.com/-aether/p/12331992.html