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;
}

浙公网安备 33010602011771号