Codeforces Round #554 ( div.2 ) 总结

应该经常需要锻炼一下英语阅读理解能力和代码能力,所以以后还是需要多打打CF。

今天大概就是水一水找找感觉。

A. Neko Finds Grapes

n个箱子,m个钥匙,每个箱子有参数$a_i$,每个钥匙有参数$b_i$

当且仅当,$a_i + b_j \equiv 1 (mod 2)$,则说箱子和钥匙配对成功。

注意到,一个箱子只能和一个钥匙配对最多一次。

要求最大化配对数。

Solution : 直接统计即可,考虑配对只可能是奇数+偶数或者偶数+奇数。

所以答案必然是$\min\{ cnta_{奇} , cntb_{偶}\} +\min\{ cnta_{偶} , cntb_{奇}\}  $

# include <bits/stdc++.h>
using namespace std;
int cntA[2],cntB[2];
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) {
        int t; scanf("%d",&t);
        cntA[t%2]++;
    } 
    for (int i=1;i<=m;i++) {
        int t; scanf("%d",&t);
        cntB[t%2]++;
    }
    int ans=min(cntA[1],cntB[0])+min(cntA[0],cntB[1]);
    printf("%d\n",ans);
    return 0;
}
A.cpp

B. Neko Performs Cat Furrier Transform

定义在一个数$x$上的A,B两种操作,

A操作:$x=x \bigoplus  (2^n-1)$(其中$n$的值可以自己选定)

B操作:$x=x+1$ 

要求A,B两个操作交替进行,要求输出方案将$x$的最终值变成$2^m-1$即可。

要求步骤数不超过40步,但是不要求最短。

Solution:事实上A操作的意图是将数字的末若干位取反。B操作含义是将数最后一位+1,并且进位。

考虑一个贪心,如果每次取将第一个0出现的位置往低位取反,然后最后在末尾+1,那么每次至少消去第一个0出现的位置的一个0

所以必然2步就可以至少删去1个0,那么显然可以在40步内完成任务。

  本题主要需要注意,操作步数不一定是偶数,可能最后的B操作不做,操作步数是奇数的,需要特判。

# include <bits/stdc++.h>
using namespace std;
int base[25];
int ttt[100];
int getbit(int x)
{
    int t=x,cnt=0;
    while (t) t/=2,cnt++;
    return cnt;
}
bool check(int x)
{
    for (int i=0;i<=20;i++)
     if (x==base[i]) return 1;
    return 0;
}
int main()
{
    int uuu=0;
    int x,ans=0; scanf("%d",&x);
    for (int i=0;i<=20;i++) base[i]=(1<<i)-1;
    if (check(x)) {
        puts("0"); return 0;
    }
    while (true) {
        int p=getbit(x);
        bool flag=false;
        for (int i=p-2;i>=0;i--)
         if (((1<<i)&x)==0) {
             x=x^((1<<(i+1))-1); ttt[++ttt[0]]=i+1; uuu++;
            if (check(x)) flag=true; 
            if (flag) break;
            x=x+1; uuu++;
             if (check(x)) flag=true; 
            if (flag) break;
             break;
         }
        if (flag) break;
    }
    printf("%d\n",uuu);
    for (int i=1;i<=ttt[0];i++)
     printf("%d ",ttt[i]);
    return 0;
}
B.cpp

 C. Neko does Maths

给出数$a,b$,要求先最小化$lcm(a+k,b+k)$的同时,最小化$k$的值。

Solution:不妨设$a>b$ 

显然$lcm(a+k,b+k)=\frac{(a+k)(b+k)}{gcd(a+k,b+k)}$

由辗转相减法可知$gcd(a,b)=gcd(b,a-b)$,

所以原式可化为$lcm(a+k,b+k)=\frac{(a+k)(b+k)}{gcd(b+k,a-b)}$

对于$a-b$的值是定值,那么我们就可以枚举$a-b$的因子$w$然后反过来O(1)求出最小的$k$就行了。

若$b \%  w = 0$ 那么 $k = 0$ 否则 $k = (\left \lfloor \frac{b}{w} \right \rfloor + 1)w-b$

复杂度$ O(\sqrt{a-b}) $

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e5+10;
int n,A[N];
signed main()
{
    int a,b; scanf("%lld%lld",&a,&b);
    if (a<b) swap(a,b); int d=a-b;
    for (int i=1;i<=sqrt(d);i++)
     if (d%i==0) A[++n]=i,A[++n]=d/i;
    int ans=1ll<<62,pr=0; 
    for (int i=1;i<=n;i++) {
        int w=A[i],k=(b%w)?(b/w+1)*w-b:0ll;
        if (ans>(a+k)*(b+k)/w) ans=(a+k)*(b+k)/w,pr=k;
    } 
    cout<<pr<<'\n';
    return 0;
}
C.cpp

猜你喜欢

转载自www.cnblogs.com/ljc20020730/p/10766001.html