2020牛客多校第四场于2020/7/20-21

前两天参加了多校第三场,感慨就是菜是真的菜,代码写得还不规范,碰上一个想要卡时间复杂度的出题人直接GG。
说到G,牛客多校第三场的G题还不会,希望放到本篇里面继续学习。
2020/7/20目标:
牛客多校第四场rank:top500
完成B,F

B

解读数学表达式,再加上少许尝试,发现答案为pow(c,cnt)
其中cnt是n的质因数的个数
需要打表
TLE了两次

F

题意:
已知AB//CD所在直线,知道AC,AD,BC,BD的值,问确定CD的顺序。
连接AD,AC,BC,BD
又由最简单的三角形两边之和大于第三边
发现:AD+BC>AC+BD=>顺序为CD
反之顺序为DC

H

题意:
从1到n中最多能取出几对最大公因数不为1的数对
我的思考:
打表找出n/2到n中的素数个数m,(n-m-1)/2即为数对数。
困难:
用什么构造方法可以构造该数对,尝试了dp(后来自己证明了是错的),贪心(代码就不发上来了)
题解:
还是构造的方法
首先应该考虑有那些数不能参与匹配。显而易见1和大于n/2的素数一定没有匹配对象,可以直接忽略。
接下来考虑剩下的素数,倒序枚举每个素数p,找出所有未匹配的p的倍数,并且记下总数。 如果总数是偶数,那么这些数就可以完美两两匹配;否则留下2*p(2的倍数最为常用,可以用于应对最后剩下的数),匹配其余的数。
最后只会留下一堆偶数,而它们两两都可以随意匹配。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn=2e5+5;
bool u[maxn];//==1为素数 
int su[maxn];
int suc[maxn];
void prepare(int n)
{
    int num=1;
    memset(u,true,sizeof(u));
    for(int i=2;i<=n;i++)
    {  
        if(u[i]) su[num++]=i;
        for(int j=1;j<num;j++)
        {
            if(i*su[j]>n) break;
            u[i*su[j]]=false;
            if(i%su[j]==0) break;
        }
    }
    for(int i=2;i<n;i++)
    {
    	if(u[i]==1)
    	{
    		suc[i]=suc[i-1]+1;
		}
		else suc[i]=suc[i-1];
	}
}
bool leap[maxn];
int main()
{
    int T;
	scanf("%d",&T);
    prepare(2e5+1);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        
    {
		
        int cnt=0;
        memset(leap,0,sizeof leap);
        int ans=n-1-(suc[n]-suc[n/2]);
        printf("%d\n",ans/2);
        stack<int> s;
        
        for(int i=n/2;i>=2;i--)
        {
        	stack<int> ss;
        	if(u[i]==1)
        	{
        		int cnt=0;
        		for(int j=1;j<=n/i;j++)
        		{
        			if(leap[i*j]==0)
        			{
        				cnt++;
					}
				}
				if(cnt%2==0)
				{
					for(int j=1;j<=n/i;j++)
					{
						
						if(leap[i*j]==0)
						{
							leap[i*j]=1;
							ss.push(i*j);
						}
						if(ss.size()==2)
						{
							cout<<ss.top();
							ss.pop();
							cout<<" "<<ss.top()<<endl;
							ss.pop();
						}
						
					}
				}
				if(cnt%2==1)
				{
					s.push(2*i);
					leap[2*i]=1;					
					for(int j=1;j<=n/i;j++)
					{
						if(leap[i*j]==0)
						{
							leap[i*j]=1;
							ss.push(i*j);
						}
						if(ss.size()==2)
						{
							cout<<ss.top();
							ss.pop();
							cout<<" "<<ss.top()<<endl;
							ss.pop();
						}
					}
					leap[2*i]=0;
				}
				
			}
        	
		}
		
		//cout<<endl;
	}
    }
}

本次多校难度较高,区分度也比较小,我队做出来2题的时间还是比较快的,但是由于罚时未能进入前500,(主要我的两个TLE和两个WA),以后还要注意。

抽空补I题。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值