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? '
    ':' ');
    	}
    }
    
  • 相关阅读:
    界面控件DevExpress WPF入门 表达式编辑器功能
    Telerik UI for WPF全新版本——拥有Office2019高对比度主题
    DevExpress报表控件v21.2 全新的Visual Studio报表设计器
    报告生成器FastReport .NET入门指南 在Linux中启动应用程序
    文档控件DevExpress Office File API v21.2 自定义字体加载引擎
    UI组件库Kendo UI for Angular入门 如何开始使用图表功能
    WPF界面工具Telerik UI for WPF入门级教程 设置一个主题(二)
    DevExtreme初级入门教程(React篇) TypeScript支持
    报表开发利器FastReport .NET v2022.1 添加关键对象和属性
    python项目打包(一) setup.py、Python源代码项目结构
  • 原文地址:https://www.cnblogs.com/-aether/p/12331992.html
Copyright © 2011-2022 走看看