zoukankan      html  css  js  c++  java
  • [Codeforces Global Round 14]

    打挺差的。
    不过\(C,D\)一眼秒了,大概是对这几个月努力的一个结果?
    \(B\)玄学错误挂了两发。
    脑子痛然后打到一半就去睡觉了。
    ————————————————————————————————————————————————
    以上是闲话部分。

    \(A\)
    考虑判断是否存在一个前缀和不满足条件。
    有后缀的话拉一个过来交换就行,否则就是没有方案。

    A
    // code by fhq_treap
    #include<bits/stdc++.h>
    #define ll long long
    #define N 300005
     
    inline ll read(){
        char C=getchar();
        ll A=0 , F=1;
        while(('0' > C || C > '9') && (C != '-')) C=getchar();
        if(C == '-') F=-1 , C=getchar();
        while('0' <= C && C <= '9') A=(A << 1)+(A << 3)+(C - 48) , C=getchar();
        return A*F;
    }
     
     
    struct P{
    	int to,next;
    };
     
    struct Map{
    	P e[N << 1];
    	int head[N],cnt;
    	Map(){
    		std::memset(head,0,sizeof(head));
    		cnt = 0;
    	}
    	inline void add(int x,int y){
    		e[++cnt].to = y;
    		e[cnt].next = head[x];
    		head[x] = cnt;
    	}
    };
     
    ll t;
    ll num[N];
    ll n,k;
     
    int main(){
    	t = read();
    	while(t -- ){
    		n = read(),k = read();
    		ll sum = 0,s = 0;
    		for(int i = 1;i <= n;++i)
    		num[i] = read(),s += num[i];
    		if(s == k)
    		puts("NO");
    		else{
    			puts("YES");
    		for(int i = 1;i <= n;++i){
    			sum += num[i];
    			if(sum == k){
    				std::cout<<num[i + 1]<<" "<<num[i]<<" ";
    				++i;
    			}
    			else
    			std::cout<<num[i]<<" ";
    		}
    			puts("");
    		}
    	}
    }
    

    \(B\)
    考虑基本单位是一个边长为\(1\)\(sqrt(2)\)的单位正方形。
    判断是否能有这样平方数个单位正方形。
    玄学错误挂了两发,重写一下就过了,怪离谱的

    B
    // code by fhq_treap
    #include<bits/stdc++.h>
    #define ll long long
    #define N 300005
    
    inline ll read(){
        char C=getchar();
        ll A=0 , F=1;
        while(('0' > C || C > '9') && (C != '-')) C=getchar();
        if(C == '-') F=-1 , C=getchar();
        while('0' <= C && C <= '9') A=(A << 1)+(A << 3)+(C - 48) , C=getchar();
        return A*F;
    }
    
    
    struct P{
    	int to,next;
    };
    
    struct Map{
    	P e[N << 1];
    	int head[N],cnt;
    	Map(){
    		std::memset(head,0,sizeof(head));
    		cnt = 0;
    	}
    	inline void add(int x,int y){
    		e[++cnt].to = y;
    		e[cnt].next = head[x];
    		head[x] = cnt;
    	}
    };
    
    ll t;
    
    int main(){
    	t = read();
    	while(t -- ){
    		ll x = read();
    		if(x % 2 == 0 && ((int)sqrt(x / 2) * (int)sqrt(x / 2) == x / 2))
    		puts("YES");
    		else{
    			if(x % 4 == 0 && ((int)sqrt(x / 4) * (int)sqrt(x / 4) == x / 4))
    			puts("YES");
    			else
    			puts("NO");
    		}
    	}
    }
    
    
    

    \(C\)
    考虑题目的意思就是让这\(m\)组中最小的最大,最大的最小。
    那么考虑派完序,一个接一个往这\(m\)组丢,具体实现看代码。

    C
    // code by fhq_treap
    #include<bits/stdc++.h>
    #define ll long long
    #define N 300005
    
    inline ll read(){
        char C=getchar();
        ll A=0 , F=1;
        while(('0' > C || C > '9') && (C != '-')) C=getchar();
        if(C == '-') F=-1 , C=getchar();
        while('0' <= C && C <= '9') A=(A << 1)+(A << 3)+(C - 48) , C=getchar();
        return A*F;
    }
    
    
    struct P{
    	int to,next;
    };
    
    struct Map{
    	P e[N << 1];
    	int head[N],cnt;
    	Map(){
    		std::memset(head,0,sizeof(head));
    		cnt = 0;
    	}
    	inline void add(int x,int y){
    		e[++cnt].to = y;
    		e[cnt].next = head[x];
    		head[x] = cnt;
    	}
    };
    
    ll t;
    ll n,m,k;
    ll s[N];
    
    struct T{
    	ll id,v,to;
    }num[N];
    
    bool cmp1(T a,T b){
    	return a.v < b.v;
    }
    
    bool cmp2(T a,T b){
    	return a.id < b.id;
    }
    
    int main(){
    	t = read();
    	while(t -- ){
    		n = read(),m = read(),k = read();
    		for(int i = 1;i <= n;++i)
    		num[i].id = i,num[i].v = read();
    		std::sort(num + 1,num + n + 1,cmp1);
    		for(int i = 1;i <= m;++i)
    		s[i] = 0;
    		for(int i = 1;i <= n;++i)
    		s[(i % m) + 1] += num[i].v,num[i].to = (i % m) + 1;
    		ll minn = 0x3f3f3f3f,maxx = -0x3f3f3f3f;
    		for(int i = 1;i <= m;++i)
    		minn = std::min(minn,s[i]),maxx = std::max(maxx,s[i]);
    		if(maxx - minn <= k){
    			puts("YES");
    			std::sort(num + 1,num + n + 1,cmp2);
    			for(int i = 1;i <= n;++i)
    			std::cout<<num[i].to<<" ";
    			puts("");
    		}
    		else
    		puts("NO");
    	}
    }
    

    \(D\)
    看出来如果\(l,r\)不相等,则一定要从多的一边向少的一边转变,那么这个时候尽量让能匹配的袜子多就行了。

    D
    // code by fhq_treap
    #include<bits/stdc++.h>
    #define ll long long
    #define N 300005
    
    inline ll read(){
        char C=getchar();
        ll A=0 , F=1;
        while(('0' > C || C > '9') && (C != '-')) C=getchar();
        if(C == '-') F=-1 , C=getchar();
        while('0' <= C && C <= '9') A=(A << 1)+(A << 3)+(C - 48) , C=getchar();
        return A*F;
    }
    
    
    struct P{
    	int to,next;
    };
    
    struct Map{
    	P e[N << 1];
    	int head[N],cnt;
    	Map(){
    		std::memset(head,0,sizeof(head));
    		cnt = 0;
    	}
    	inline void add(int x,int y){
    		e[++cnt].to = y;
    		e[cnt].next = head[x];
    		head[x] = cnt;
    	}
    };
    
    ll t,n,l,r;
    ll c[N],lc[N],rc[N],cnt[N];
    bool del[N];
    
    int main(){
    	t = read();
    	while(t -- ){
    		n = read(),l = read(),r = read();
    		for(int i = 1;i <= n;++i)
    		c[i] = read(),lc[c[i]] = 0,rc[c[i]] = 0,cnt[c[i]] = 0,del[c[i]] = 0;
    		for(int i = 1;i <= l;++i)
    		lc[c[i]] ++ ,cnt[c[i]] ++ ;
    		for(int i = l + 1;i <= n;++i)
    		rc[c[i]] ++ ,cnt[c[i]] ++ ;
    		for(int i = 1;i <= l;++i)
    		if(rc[c[i]])
    		rc[c[i]] -- ,lc[c[i]] -- ,cnt[c[i]] -= 2;
    		ll need = abs(r - l) / 2;
    		if(l > r){
    			for(int i = 1;i <= l;++i){
    				while(need && lc[c[i]] >= 2)
    				lc[c[i]] -= 2,cnt[c[i]] -= 2,need -- ;
    			}
    		}else{
    			if(l < r){
    				for(int i = l + 1;i <= n;++i)
    				while(need && rc[c[i]] >= 2)
    				rc[c[i]] -= 2,cnt[c[i]] -= 2,need -- ;
    			}
    		}
    		ll ans = 0;
    		for(int i = 1;i <= n;++i){
    			if(!del[c[i]])
    			del[c[i]] = 1,ans += cnt[c[i]] ;
    		}
    		std::cout<<ans / 2 + abs(r - l) / 2<<std::endl;
    	}
    }
    
    
    

    \(E\)
    数数题。
    大概看出来一点东西。
    不过连续的一段的操作自己不会算方案数。
    后来补的。
    考虑计\(f[i][j]\)为开到\(i\)台,\(j\)台为自己手动开的。
    那么就是考虑连续一段(即这一段没有自动开的)的方案数了
    长度为\(l\)的一段则必有选择一个\(i\),表示从他开始向两边扩展,则还有\(l - 1\)个位置,有\(i - 1\)个数要丢进去,考虑前\(i - 1\)个数一旦确定,则整个序列确定。
    所以连续一段的答案是\(C_{l - 1}^0 + C_{l - 1}^1 ..... = 2^{l - 1}\)
    所以\(f[i + k + 1][j + k] = f[i][j] * 2^{k - 1} * C_{j + k}^k\)

    E
    #include<iostream>
    #include<cstdio>
    #define ll long long
    #define N 500
    
    ll mod;
    ll f[N][N];
    ll n;
    
    inline ll pow(ll a,ll b){
    	ll ans = 1;
    	while(b){
    		if(b & 1)
    		ans = ans * a % mod;
    		a = a * a % mod;
    		b >>= 1;
    	}
    	return  ans;
    }
    
    ll s[N],inv[N];
    
    inline ll c(ll a,ll b){
    	return s[a] * inv[a - b] % mod * inv[b] % mod;
    }
    
    ll ans = 0;
    
    int main(){
    	scanf("%lld%lld",&n,&mod);
    	s[0] = 1;
    	for(int i = 1;i <= 405;++i)
    	s[i] = s[i - 1] * i % mod;
    	inv[405] = pow(s[405],mod - 2);
    	for(int i = 404;i >= 1;--i)
    	inv[i] = inv[i + 1] * (i + 1) % mod;
    	for(int i = 1;i <= n;++i)
    	f[i][i] = pow(2,i - 1);
    	for(int i = 1;i <= n;++i)
    	for(int j = 1;j <= i;++j)
    	for(int k = 1;i + k + 1 <= n;++k)
    	f[i + k + 1][j + k] = (f[i + k + 1][j + k] +  f[i][j] * pow(2,k - 1) % mod * c(j + k,k) % mod) % mod;
    	for(int i = 1;i <= n;++i)
    	ans = (f[n][i] + ans) % mod;
    	std::cout<<ans<<std::endl; 
    }
    

    \(F\)
    果然这题好做很多?
    虽然比赛的时候看了一眼就睡了。
    后来补的。
    很简单的一个构造就是了。
    考虑两个点合在一起时把权值和边集都合在一起。
    每次挑最大的点和周围一个点合并。

  • 相关阅读:
    C#调用存储过程的几个方法
    easyui 获取焦点
    easyui datagrid 添加统计行
    js 序列化form
    post 加返回判断
    启动journalnode时出现问题
    安装zookeeper集群及出现的问题
    win7旗舰版(64位)环境下oracle11g的安装方法(转)
    jdbc连接各种数据库方式列表
    在Windows平台上使用XManager 3.0连接Redhat 企业版 5和6.
  • 原文地址:https://www.cnblogs.com/dixiao/p/14728152.html
Copyright © 2011-2022 走看看