A. To Zero
先减 \(k\),变成偶数,然后不停减 \(k-1\) 。
#include<bits/stdc++.h>
using namespace std;
#define i128 __int128
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-x))
#define It set<int>::iterator
//#define ls (rt<<1)
//#define rs (rt<<1|1)
//#define mid (l+r>>1)
//#define lson tr[rt].ls
//#define rson tr[rt].rs
//#define ls1 tr[rt1].ls
//#define rs1 tr[rt1].rs
//#define ls2 tr[rt2].ls
//#define rs2 tr[rt2].rs
#define pb emplace_back
const int mod=998244353;
int ksm(int x,int y){int res=1;while(y){if(y&1)res=1LL*res*x%mod;x=1LL*x*x%mod;y>>=1;}return res;
}
int t;
int n,k;
void solve(){scanf("%d%d",&n,&k);n-=k;printf("%d\n",(n+k-2)/(k-1)+1);
}
int main(){scanf("%d",&t);while(t--)solve();return 0;
}
B. Array Recoloring
显然,最后取到最大的 \(k+1\) 个数最优。
设选了 \(p_1 , p_2 \dots p_k\) ,那么可以控制最后一个选 \(a_1,a_2\) 和 \(p_1\) 到 \(p_k\)中的任何一个。
那么对于 \(k \geq 2\) 时,只要取到最大 \(k+1\) 个数中,最左边和最右边的数即可。
对于 \(k = 1\) 时,要么 \(a_1+a_n\) ,要么 \(\max(a_1,a_n)+\max(a_2,\dots,a_{n-1})\) 。
#include<bits/stdc++.h>
using namespace std;
#define i128 __int128
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-x))
#define It set<int>::iterator
//#define ls (rt<<1)
//#define rs (rt<<1|1)
//#define mid (l+r>>1)
//#define lson tr[rt].ls
//#define rson tr[rt].rs
//#define ls1 tr[rt1].ls
//#define rs1 tr[rt1].rs
//#define ls2 tr[rt2].ls
//#define rs2 tr[rt2].rs
#define pb emplace_back
const int mod=998244353;
int ksm(int x,int y){int res=1;while(y){if(y&1)res=1LL*res*x%mod;x=1LL*x*x%mod;y>>=1;}return res;
}
int t;
int n,k,a[5005];
void solve(){scanf("%d%d",&n,&k);for(int i=1;i<=n;i++)scanf("%d",&a[i]);if(k==1){int res=a[1]+a[n];int mx=0;for(int i=2;i<n;i++)mx=max(mx,a[i]);res=max(res,mx+max(a[1],a[n]));printf("%d\n",res);return ;}sort(a+1,a+1+n);ll res=0;for(int i=n-k;i<=n;i++)res+=a[i];printf("%lld\n",res);
}
int main(){scanf("%d",&t);while(t--)solve();return 0;
}
C. Two Colors
对于两个颜色,分别有 \(a,b\) 个,其中 \(a\leq b\) 且 \(a+b\geq n\) 。
那么有 \(\min(b,n-1)-\max(n-a,1)+1\) 个方案。
拆个贡献就做完了。
(代码里把 \(+1\) 放到 \(a\) 的贡献里面了。)
#include<bits/stdc++.h>
using namespace std;
#define i128 __int128
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-x))
#define It set<int>::iterator
//#define ls (rt<<1)
//#define rs (rt<<1|1)
//#define mid (l+r>>1)
//#define lson tr[rt].ls
//#define rson tr[rt].rs
//#define ls1 tr[rt1].ls
//#define rs1 tr[rt1].rs
//#define ls2 tr[rt2].ls
//#define rs2 tr[rt2].rs
#define pb emplace_back
const int mod=998244353;
int ksm(int x,int y){int res=1;while(y){if(y&1)res=1LL*res*x%mod;x=1LL*x*x%mod;y>>=1;}return res;
}
int t;
int n,m,a[200005];
void solve(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%d",&a[i]);sort(a+1,a+1+m);ll res=0;for(int i=1;i<=m;i++){int l=i+1,r=m,pos2=0,pos1=0;while(l<=r){int mid=(l+r>>1);if(a[mid]+a[i]>=n)pos2=mid,r=mid-1;else l=mid+1;}if(pos2)res-=(ll)(m-pos2+1)*max(n-a[i]-1,0);l=1,r=i-1;while(l<=r){int mid=(l+r>>1);if(a[mid]+a[i]>=n)pos1=mid,r=mid-1;else l=mid+1;}if(pos1)res+=(ll)(i-pos1)*min(a[i],n-1);
// printf("%d %d %d\n",i,pos1,pos2);}printf("%lld\n",res*2);
}
int main(){scanf("%d",&t);while(t--)solve();return 0;
}
D. Equalization
最后剩下来的一定是 \(x\) 和 \(y\) 的一个公共前缀,或者删完。
考虑预处理 \(f_{i,j}\) 表示一个要删 \(i\) 个,一个要删 \(j\) 个,最少的代价。
这个可以用一个01背包来维护,然后就做完了。
注意,\(f_{i,j}\) 没有单调性,比如 \(f_{10,4}\gt f_{10,5}\),所以枚举删完的情况要枚举完整。
#include<bits/stdc++.h>
using namespace std;
#define i128 __int128
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-x))
#define It set<int>::iterator
//#define ls (rt<<1)
//#define rs (rt<<1|1)
//#define mid (l+r>>1)
//#define lson tr[rt].ls
//#define rson tr[rt].rs
//#define ls1 tr[rt1].ls
//#define rs1 tr[rt1].rs
//#define ls2 tr[rt2].ls
//#define rs2 tr[rt2].rs
#define pb emplace_back
const int mod=998244353;
int ksm(int x,int y){int res=1;while(y){if(y&1)res=1LL*res*x%mod;x=1LL*x*x%mod;y>>=1;}return res;
}
int t;
ll x,y,f[75][75];
void init(){memset(f,0x3f,sizeof(f));f[0][0]=0;for(int k=1;k<=60;k++)for(int i=70;i>=0;i--)for(int j=70;j>=0;j--){if(i>=k)f[i][j]=min(f[i][j],f[i-k][j]+(1LL<<k));if(j>=k)f[i][j]=min(f[i][j],f[i][j-k]+(1LL<<k));}
}
int ax[75],cntx,ay[75],cnty;
void solve(){for(int i=1;i<=cntx || i<=cnty;i++)ax[i]=ay[i]=0;cntx=cnty=0;scanf("%lld%lld",&x,&y);while(x)ax[++cntx]=x&1,x>>=1;while(y)ay[++cnty]=y&1,y>>=1;reverse(ax+1,ax+1+cntx);reverse(ay+1,ay+1+cnty);ll res=3e18;for(int i=1;i<=cntx && i<=cnty;i++){if(ax[i]!=ay[i])break;res=min(res,f[cntx-i][cnty-i]);}for(int i=cntx;i<=70;i++)for(int j=cnty;j<=70;j++)res=min(res,f[i][j]);printf("%lld\n",res);
}
int main(){scanf("%d",&t);init();while(t--)solve();return 0;
}
E. XOR Matrix
显然,\(a,b\) 中不能出现至少3个不同的数。
如果都只有一个不同的数,方案数为 \((A+1)(B+1)\) 。
如果有一个有一个不同的数。(设它是 \(a\),\(b\) 的情况是类似的)
那么方案数为 \((A+1)(^{B+1}_{\ \ \ 2})(2^m-2)\) 。
对于两个都选两个不同数的情况,设选的数为 \(a,b,c,d\) ,其中 \(a\neq b,c\neq d\) 。
得到的异或和为 \(a \bigoplus c,a\bigoplus d,b \bigoplus c,b \bigoplus d\) 。
其中必须有两对是相等的。
那么只能是 \(a \bigoplus c = b \bigoplus d\) 。
也就是4个数的异或和为0。
于是可以用数位dp来做,令 \(f_{i,j}\) 表示枚举到第 \(i\) 位,\(j\) 表示4个数是否顶着上限。(压了个位)
顶着上限的意思是,到枚举到的 \(i\) 为止,它的每一位都和上限一样。
转移是容易的。
#include<bits/stdc++.h>
using namespace std;
#define i128 __int128
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-x))
#define It set<int>::iterator
//#define ls (rt<<1)
//#define rs (rt<<1|1)
//#define mid (l+r>>1)
//#define lson tr[rt].ls
//#define rson tr[rt].rs
//#define ls1 tr[rt1].ls
//#define rs1 tr[rt1].rs
//#define ls2 tr[rt2].ls
//#define rs2 tr[rt2].rs
#define pb emplace_back
const int mod=998244353;
int ksm(int x,int y){int res=1;while(y){if(y&1)res=1LL*res*x%mod;x=1LL*x*x%mod;y>>=1;}return res;
}
bool check(int x){int sum=(x&1)+((x>>1)&1)+((x>>2)&1)+((x>>3)&1);return (sum&1);
}
int t;
int n,m,A,B;
bool check0(int p,int q,int r){int q0=q&1,q1=(q>>1)&1,q2=(q>>2)&1,q3=(q>>3)&1;int r0=r&1,r1=(r>>1)&1,r2=(r>>2)&1,r3=(r>>3)&1;int t0=(A>>p)&1,t1=(B>>p)&1;if(!t0 && q0 && r0)return 1;if(!t0 && q1 && r1)return 1;if(!t1 && q2 && r2)return 1;if(!t1 && q3 && r3)return 1;return 0;
}
int get(int p,int q,int r){int q0=q&1,q1=(q>>1)&1,q2=(q>>2)&1,q3=(q>>3)&1;int r0=r&1,r1=(r>>1)&1,r2=(r>>2)&1,r3=(r>>3)&1;int t0=(A>>p)&1,t1=(B>>p)&1,res=0;if(q0 && t0==r0)res|=1;if(q1 && t0==r1)res|=2;if(q2 && t1==r2)res|=4;if(q3 && t1==r3)res|=8;return res;
}
int work1(){int res=0;res=(res+(ll)(B+1)*B/2%mod*(A+1)%mod*(ksm(2,m)-2)%mod)%mod;res=(res+(ll)(A+1)*A/2%mod*(B+1)%mod*(ksm(2,n)-2)%mod)%mod;res=(res+(ll)(A+1)*(B+1))%mod;return res;
}
int f[35][19];
int work2(){memset(f,0,sizeof(f)); f[30][15]=1;for(int i=29;i>=0;i--)for(int j=0;j<=15;j++)for(int k=0;k<=15;k++)if(!check(k)){if(check0(i,j,k))continue;int uj=get(i,j,k);
// printf("%d %d %d %d\n",i,j,k,uj);f[i][uj]=(f[i][uj]+f[i+1][j])%mod;}int res=0;for(int i=0;i<=15;i++)res=(res+f[0][i])%mod;res=(res-(ll)(A+1)*(B+1)%mod+mod)%mod;res=(ll)res*(ksm(2,n)-2)%mod*(ksm(2,m)-2)%mod*ksm(4,mod-2)%mod;return res;
}
void solve(){scanf("%d%d%d%d",&n,&m,&A,&B);int res=work1()+work2();res%=mod;printf("%d\n",res);
}
int main(){scanf("%d",&t);while(t--)solve();return 0;
}