应该经常需要锻炼一下英语阅读理解能力和代码能力,所以以后还是需要多打打CF。
今天大概就是水一水找找感觉。
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; }
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; }
给出数$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; }