zoukankan      html  css  js  c++  java
  • Codeforces Round #511 (Div. 2) A~D题解

    A. Little C Loves 3 I

    题目大意:给定一个(n)构造(a+b+c=n)且三者都不是3的倍数.

    思路

    显然直接讨论(n)即可.

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)	
    
    
    int main()
    {
    	int n;scanf("%d",&n);
    	int a = n / 3,b = n / 3,c = n - a - b;
    	if(n % 3 == 0)
    	{
    		if(a % 3 == 0)	b += 2,--a,--c;
    	}
    	else if(n % 3 == 1)
    	{
    		if(a % 3 == 0)	++b,--a;
    		else if(c % 3 == 0)	++c,--a;
    	}
    	else if(n % 3 == 2)
    	{
    		if(a % 3 == 0)	++b,--a;
    		else if(c % 3 == 0)	--c,++b;
    	}
    	printf("%d %d %d",a,b,c);
        return 0;
    }
    

    B. Cover Points

    题目大意:平面上有(n)个点,找一个等腰三角形,两条边平行于坐标轴,且所有点在被覆盖的范围内.输出三角形最短一遍的长度.

    思路

    题面不知道怎么写的.

    由于条件太强所以直线是(y=-x).所以直接讨论每个点被恰好覆盖到的时候,需要的长度就可以了.

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)	
    
    
    int main()
    {
    	int n;scanf("%d",&n);
    	int res = 0;
    	while(n--)
    	{
    		int x,y;scanf("%d%d",&x,&y);
    		res = max(res,x + y);
    	}
    	printf("%d",res);
        return 0;
    }
    

    C. Enlarge GCD

    题目大意:有(n)个数,求最少删除多少个数能使整个数列的(gcd)上升.无解输出-1.

    数据范围:

    (2 leq n leq 3 *10^5)

    (1 leq a_i leq 1.5*10^7)

    思路

    一开始把所有的数直接除掉最开始的数列的(gcd).之后拿到的数列(gcd=1).

    现在的问题就是最少删除多少个数可以使整个数列的(gcd>1).

    那么显然也是套路,枚举每个质数(p)在所有数中出现的次数(c),那么(n-c)就是答案.排除掉(c=0)的情况找最小值就可以了.

    但是这个题比较无聊,他需要特殊实现,为了卡根号算法导致这个题很无语:

    枚举(p)的时候不直接枚举所有的数,而是枚举数域,也就是说在之前先在数域上把每个数出现的次数找出来,之后再枚举(p)以及(p)的倍数看有多少个位置被覆盖了,这样枚举倍数的做法类似于区间筛约数,复杂度是调和级数.

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)	
    
    const int N = 3e5+7,M = 1.5e7+7;
    int a[N];
    int primes[M / 10],cnt;
    bool st[M];
    int c[M];
    
    void init(int N)
    {
    	for(int i = 2;i <= N;++i)
    	{
    		if(!st[i])	primes[cnt++] = i;
    		for(int j = 0;j < cnt && primes[j] * i <= N;++j)
    		{
    			st[i * primes[j]] = 1;
    			if(i % primes[j] == 0)	break;
    		}
    	}
    }
    
    int gcd(int x,int y)
    {
    	if(y == 0)	return x;
    	return gcd(y,x % y);
    }
    
    int main()
    {
    	int n,g = 0;scanf("%d",&n);
    	forn(i,1,n)	scanf("%d",&a[i]),g = gcd(g,a[i]);
    	forn(i,1,n)	a[i] /= g;
        
        int maxv = 0;
        forn(i,1,n)	maxv = max(maxv,a[i]),++c[a[i]];
    
        init(maxv);
        
        int res = n;
        forn(j,0,cnt - 1)
        {
        	int t = 0;
        	for(int p = primes[j];p <= maxv;p += primes[j])	t += c[p];
    		if(t == 0 || t == n)	continue;
        	res = min(res,n - t);
        }
        
        printf("%d",res == n ? -1 : res);
        return 0;
    }
    

    D. Little C Loves 3 II

    题目大意:有一个(n*m)的棋盘,每次可以往棋盘上放两个棋子,要求棋子不能重合且两个放置的棋子的曼哈顿距离必须是(3).求最多能放置多少个棋子.

    数据范围:

    (1 leq n,m leq 10^9)

    思路

    直接大力讨论:

    首先保证(nleq m).

    • (n=1)时,可以覆盖的范围以(6)为循环,那么按循环节来做,都有的部分就是(n/6*6),剩下的只有当(n\%6=4)时多加两个,(n\%6=5)时多加四个.
    • (n=2)时,可以找出来(2X4,2X5,2X6)的格子都是可以摆满的,根据赛瓦韦斯特定理,形如(4x+5y=c)的表达式,当(x,y)都是非负整数时,最大的不能表示出来的数是(x*y-x-y).也就是说最大的不能表示出来的数是(11),只需要在(11)范围之内特判,其他的都是可以表示出来的,那么当(m=1,m=2)时结果为(0),当(m=3)时结果为(4),当(m=7)时结果为(12).其余情况答案都是(m*2).
    • (ngeq3)时,棋局是可以任意摆满的,当(n*m)是奇数时多了一个格子删去,偶数是答案就是(n*m).证明可以通过一些可以摆满的块与上面相同来说明,例如(3X3)的恰好值多一个,(4X4)(3X4)的可以摆满,结合第二个就可以做完了.

    还有一种思路是,因为距离为三所以显然可以二染色棋盘进而是一个二分图,问题等价于在二分图上求匹配.剩下的就是套路了,通过打表可以发现数值较大的时候答案就是(n*m(-1)).小范围的直接做二分图最大匹配就可以了.

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)	
    
    
    int main()
    {
    	ios::sync_with_stdio(0);cin.tie(0);
    	ll n,m;cin >> n >> m;
    	if(n > m)	swap(n,m);
    	
    	if(n == 1)	
    	{
    		if(m % 6 == 0)	cout << m << endl;
    		else
    		{
    			ll res = m / 6 * 6;
    			if(m % 6 == 4)	res += 2;
    			else if(m % 6 == 5)	res += 4;
    			cout << res << endl;
    		}
    	}
    	else if(n == 2)
    	{
    		if(m == 1)	cout << 0;
    		else if(m == 2)	cout << 0;
    		else if(m == 3)	cout << 4;
    		else if(m == 7)	cout << 12;
    		else cout << m * 2;
    	}
    	else
    	{
    		ll res = n * m;
    		if(res & 1)	--res;
    		cout << res << endl;
    	}
        return 0;
    }
    
  • 相关阅读:
    SFTP的使用
    java操作文件的创建、删除、遍历
    ios UICollectionView滑动时操作
    IOS自带json解析类解析json
    IOS把文件保存进沙盒目录
    python3.4安装suds
    Lua for windows中SciTe开启支持python的方法
    修改tabbarcontroller选中图片及选中颜色
    Android新版本SDK打开旧版本项目报错解决
    PHP5.4连接sqlserver
  • 原文地址:https://www.cnblogs.com/HotPants/p/14324761.html
Copyright © 2011-2022 走看看