Educational Codeforces Round 178 (Rated for Div. 2)

Educational Codeforces Round 178 (Rated for Div. 2)

A Three Decks

有a,b,c三副牌,从c里抽出[1,c-1]张牌分给ab两副牌使得三副牌一样多

首先考虑到(a+b+c)%3=0才满足

然后是ab两副牌的数目不能超过(a+b+c)/3

void ac()
{
	int a,b,c;
	cin>>a>>b>>c;
	if((a+b+c)%3==0)
	{
		int z=(a+b+c)/3;
		if(a>z||b>z)
			cout<<"No"<<endl;
		else
			cout<<"Yes"<<endl;
	}
	else
		cout<<"No"<<endl;
}

B Move to the End

给一个有n个数的数组a,对于[i,n],可以选择把[1,i-1]的一个数放在最右边然后求[i,n]的和(也就相当于选一个数跟a[i]换位置)

纪录每个数出现的位置然后先按照从大到小排序,相同的数按照后出现的在前面

然后遍历1<=k<=n,看看最大的数在不在[k,n]这个区间,不在的话就可以把他移过来,否则就找次大的数移过来

struct node
{
	ll num;
	ll id;
};
bool cmp(node a,node b)
{
	if(a.num==b.num)
		return a.id>b.id;
	return a.num>b.num;
}
void ac()
{
	ll n;
	cin>>n;
	vector<node>op(n+5);
	vector<ll>pre(n+5,0);
	for(int i=1;i<=n;i++)
	{
		cin>>op[i].num;
		op[i].id=i;
		pre[i]=pre[i-1]+op[i].num;
	}
	sort(op.begin()+1,op.begin()+1+n,cmp);
	int ma=1;
	for(int i=1;i<=n;i++)
	{
		ll sum;
		if(op[ma].id<n-i+1)
			sum=pre[n]-pre[n-i+1]+op[ma].num;
		else
		{
			while(op[ma].id>=n-i+1&&ma<n)
				ma++;
			sum=max(pre[n]-pre[n-i],pre[n]-pre[n-i+1]+op[ma].num);
		}
		cout<<sum<<" ";
	}
	cout<<endl;
}

C Card Game

首先考虑四种情况就是第一张牌和最后一张牌谁拿着

Alice拿1 Alice拿n

那么Alice可以只展示n然后全赢

Bob拿1 Bob拿n

那么Alice的手牌只有[2,n-1]内选,Bob只需要放n就全赢

Alice拿1 Bob拿n

Alice的[2,n-1]的手牌全被Bob手上的n克制,必输

要赢的话只能看Bob有没有[2,n-1]的牌赢下Alice手上的1

也就是[2,n-1]有'B'就是Bob赢,否则Alice赢

Alice拿n Bob拿1

可选的牌只有[2,n-1]

考虑n-1这张牌可以打赢[1,n-2],那也就是n-1这张牌在谁手上谁就赢(n>2)

void ac()
{
	int n;
	string s;
	cin>>n>>s;
	s=" "+s;
	int n1=0,nn=0;
//	1->a  2->b
	n1=(s[1]=='A'?1:2);
	nn=(s[n]=='A'?1:2);
	if(n1==1&&nn==1)
		cout<<"Alice"<<endl;
	else if(n1==1&&nn==2)
	{
		for(int i=1;i<=n;i++)
		{
			if(s[i]=='B'&&i<n)
			{
				cout<<"Bob"<<endl;
				return;
			}
		}
		cout<<"Alice"<<endl;
	}
	else if(n1==2&&nn==1)
	{
		if(n==2)
			cout<<"Bob"<<endl;
		else
		{
			if(s[n-1]=='A')
				cout<<"Alice"<<endl; 
			else
				cout<<"Bob"<<endl; 
		}
	}
	else if(n1==2&&nn==2)
		cout<<"Bob"<<endl;
}

D Array and GCD

给一个有n个数的数组a,问能删最少m个数使得这个数组能通过将一个数-1或者将一个数加上减少的次数(可以只对这个数组进行减少的操作,但是增加的操作小于减的操作)

让这个数组的每一个数>2并且任意两个数的最大公因数为1

或者这个数组只有1个数,也就是答案最大为n-1

发现只需要让n个数通过一直减变成n个不相同的质数就可以了

也就是说这n个数的和要大于前n个质数

不行的话就减去一个最小的数直到这些数的和大于前n个质数和

先求前4e5个质数然后用前缀和记录(1<=n<=4e5)

删去m个数之后的和为sum

前n-m个质数的和为pre[n-m]

比较这两个数

const int TARGET_PRIMES = 500000;
const int ESTIMATED_LIMIT = 8000000;
vector<ll>zhi;
vector<ll>pre(400005);
vector<ll>generate_primes(int n)
{
    if (n <= 0) return {};
    bitset<ESTIMATED_LIMIT + 1> sieve;
    sieve.set();
    sieve[0] = sieve[1] = false;
    vector<ll>primes;
    primes.reserve(n);
    for (int p = 2; p <= ESTIMATED_LIMIT; ++p) {
        if (sieve[p]) {
            primes.push_back(p);
            if (primes.size() == n) {
                break;
            }
            for (long long j = (long long)p * p; j <= ESTIMATED_LIMIT; j += p) {
                sieve[j] = false;
            }
        }
    }
    return primes;
}
void ac()
{
	ll n;
	cin>>n;
	ll sum=0;
	vector<ll>op(n+5);
	for(int i=1;i<=n;i++)
	{
		cin>>op[i];
		sum+=op[i];
	}
	sort(op.begin()+1,op.begin()+1+n);
	if(sum>=pre[n])
		cout<<0<<endl;
	else
	{
		for(int i=1;i<=n;i++)
		{
			sum-=op[i];
			if(sum>=pre[n-i])
			{
				cout<<i<<endl;
				return; 
			}
		}
	}
}

int main()
{
    zhi=generate_primes(TARGET_PRIMES);
    for(int i=1;i<=400000;i++)
    	pre[i]=pre[i-1]+zhi[i-1];
	int t;
    cin>>t;
    while(t--)
        ac();
    return 0;
}
posted @ 2025-04-29 10:34  怅纡  阅读(50)  评论(0)    收藏  举报