zoukankan      html  css  js  c++  java
  • Codeforces Round #696 (Div. 2)

    A. Puzzle From the Future (构造+贪心)

     
    题目链接:传送门
     

    &nsbp;
    题意:给你一个二进制的数b,问你怎么凑出一个a使得c=a+b的二进制数最大,注意此处的加和并不会产生进位,换句话说, 每一位上加和的结果可能是0,1,2三种情况,并且这里连续相同的数字会缩减成一位eg:122221 => 121
     
    解题思路:很明显不管b是什么,a的第一位肯定是1,这样才能凑出最大的c,又因为连续相同的数字会缩减成一位,所以我们可以根据前面一位的数字得出当前数字的选取,比如第一位是2,当前b的这一位是0,那我们可以选1,否则选0,其他情况亦是如此,更具前一位推后一位
    Code:

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
    	int t,n;
    	string ch;
    	scanf("%d",&t);
    	while(t--) {
    		scanf("%d",&n);
    		cin>>ch;
    		putchar('1');
    		int last = 1 + (ch[0] -'0');//表示的是前一种状态的值
    		for(int i = 1;i < n; ++i) {
    			if(last == 2) {//分为三种情况讨论
    				if(ch[i] == '1')
    					putchar('0');
    				else
    					putchar('1');
    				ch[i] = '0';
    				last = 1;
    			}
    			else if(last == 1) {
    				if(ch[i] == '1') {
    					putchar('1');
    					ch[i] = '2';
    					last = 2;
    				}
    				else {
    					putchar('0');
    					last = 0;
    				}
    				
    			}
    			else if(last == 0) {
    				putchar('1');
    				if(ch[i] == '0')
    					last = 1;
    				else if(ch[i] == '1')
    					last = 2;
    				ch[i] = '1';
    			}
    		}
    		putchar('
    ');
    	}
    	
    	return 0;
    }
    

    B. Different Divisors (欧拉筛 + 思维)

     
    题目链接:传送门
     

     
    解题思路:题目比较简短,我就不描述了,我们要找到满足这样的数a,很明显我们发现其实就是找到满足这两条规定的素数,因为他这里把1个本身也算进去了,所以我们只需要找到满足条件的两个素数即可,我们通过欧拉筛,筛出一定范围内的素数,然后找到满足素数x,y,使得 (x-1>=d且y-x>=d且x*y-y>=d)
    Code:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    queue<int> que;
    
    const int N = 1000005;
    int prime[N];
    bool vis[N];
    
    void get_prime() {
        memset(vis,true,sizeof vis);
        memset(prime,0,sizeof prime);
        vis[0] = vis[1] = false;
        for(int i = 2; i <= N; ++i) {
            if (vis[i]) {
                prime[++prime[0]] = i;
            }
            for(int j = 1;j <= prime[0] && i*prime[j] <= N; ++j) {
                vis[i * prime[j]] = false;
                if (i % prime[j] == 0)
                    break;
            }
        }
    }
    ll slove(ll d) {
    	ll ans = 1;
    	ll last = 1;//表示前一位的因子,第一个因子肯定是1
    	int cnt = 0;
    	for(int i = 1;i < prime[0]; ++i) {
    		if(prime[i] - last >= d) {
    			last = prime[i];
    			ans *= last;
    			cnt++;
    		}
    		if(cnt == 2)//找到两个即可
    			break;
    	}
    	return ans;
    }
    
    int main()
    {
    	int t;
    	get_prime();
    	scanf("%d",&t);
    	ll n;
    	while(t--) {
    		scanf("%lld",&n);
    		printf("%lld
    ",slove(n));
    	}
    	
    	return 0;
    }
    

    C. Array Destruction(思维+枚举)

     
    题目链接:传送门
     

     
    题意:给你一个2n长的数组,每次可以抛出两个价值和为x的数,并且使得x的值刷新为max(k1,k2),问你是否能将数组的数全部抛空
    解题思路:我们可以通过观察发现,数组中要是有超过两个元素不能被数组中其他元素枚举出来,就肯定不能全部抛空,更进一步我们会发现,数组每次抛出元素都是先抛出最大的元素,不然先抛了小的元素,大的元素就抛不了了,此时最大的问题便是第一个x怎么确定,其实第一个x肯定是由数组中最大的元素和一个其他的元素构成的,这个其他的元素我们不能直接得出,只能通过枚举从第一个元素枚举到第2n-1个元素,对这些x进行操作,找到了满足条件的x就跳出循环,当我们确定了第一个x,那么后续的x也就一一确定了,第二个x一定是a[2n-1],然后后续的x就是max(x,x-y),具体操作请看代码
    Code:

    #include<bits/stdc++.h>
    using namespace std;
    
    struct Node {
    	int x,y;
    };
    
    int n,t,k;
    vector<int> V;
    
    bool fg(vector<int> a, int x) {
    	multiset<int> S;
    	int key = x;
    	for(auto it : a) {
    		S.insert(it);
    	}
    	vector<Node> ans;
    	for(int i = 0;i < n; ++i) {//判断当前传进来的x是否满足凑出n对
    		auto it1 = S.end();//找到集合最大的元素
    		it1--;
    		int y = x - *it1;//x对应的另一半
    		S.erase(it1);
    		auto it2 = S.find(y);
    		if(it2 == S.end()) {//如果在凑的中途有一个x没有凑出,那么就是当前的传进俩的x不能全部抛出
    			return true;
    		}
    		S.erase(it2);
    		ans.push_back({x-y,y});
    		x = max(x-y,y);
    	}
    	puts("YES");
    	printf("%d
    ",key);
    	for(int i = 0,len = ans.size();i < len; ++i) {
    		printf("%d %d
    ",ans[i].x,ans[i].y);
    	}
    	return false;
    }
    
    
    int main()
    {
    	scanf("%d",&t);
    	while(t--) {
    		V.clear();
    		scanf("%d",&n);
    		for(int i = 0;i < 2 * n; ++i) {
    			scanf("%d",&k);
    			V.push_back(k);
    		}
    		sort(V.begin(),V.end());
    		bool is = true;
    		for(int i = 0;i < 2 * n - 1; ++i) {
    			int x = V[i] + V[2 * n - 1];
    			is = fg(V,x);
    			if(!is)
    				break;
    		}
    		if(is) {
    			puts("NO");
    		}
    	}
    	return 0;
    }
    

     
    OVER,上了117分,开心ing

  • 相关阅读:
    算数基本定理与质因数分解
    质数的两种筛法
    质数及其判法
    二十二、Spring MVC与Structs2的区别总结
    二十一、MVC的WEB框架(Spring MVC)
    二十、MVC的WEB框架(Spring MVC)
    十九、Spring框架(注解方式测试)
    十八、Spring框架(AOP)
    十七、Spring框架(IOC/DI)
    创建型模式篇(建造者模式Builder Pattern)
  • 原文地址:https://www.cnblogs.com/Mangata/p/14302089.html
Copyright © 2011-2022 走看看