zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",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
    ");
    		else printf("%lld
    ",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
    ",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? '
    ':' ');
    	}
    }
    
  • 相关阅读:
    chr(9) chr(10) chr(13) chr(32)
    分割字符串
    日期提取函数EXTRACT
    数据泵在本地导出数据到远程数据库中
    CEIL与FLOOR
    GROUPING SETS与GROUP_ID
    LISTAGG
    AVG
    COUNT
    Scala 泛型类型和方法
  • 原文地址:https://www.cnblogs.com/-aether/p/12331992.html
Copyright © 2011-2022 走看看