Educational Codeforces Round 120
传送门
今天依然是4题
B题就是猜结论,其实证明应该也不难,分类讨论一下就行
C题肯定是让最小的减,然后从大到小用set操作
那么我们枚举set了多少个数,算一下至少要减多少,
需要注意的是,如果要减到的数x大于a1,那么减的这部分代价为0,直接减会减出负数导致WA
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<set>
#include<queue>
#define fo(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (int (i)=(b);(i)>=(a);(i)--)
#define mk(x,y) make_pair((x),(y))
#define lc (o<<1)
#define rc ((o<<1)|1)
#define A puts("YES")
#define B puts("NO")
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll s[N],k,n,ans,a[N],j,res,x;
int main() {
// freopen("data.in","r",stdin);
int T;
scanf("%d",&T);
while (T--) {
scanf("%lld %lld",&n,&k);
fo(i,1,n) scanf("%lld",&a[i]);
sort(a+1,a+n+1);
fo(i,1,n) s[i]=s[i-1]+a[i];
if (s[n]<=k) {
puts("0"); continue;
}
ans=s[n]-k;
fo(i,2,n) {
res=s[i-1]-a[1];
j=n-i+1;
x=(k-res)/(j+1);
if (x*(j+1) + res > k) x--;
if (x>=a[1]) ans=min(ans,j);
else ans=min(ans, j + a[1]-x);
}
printf("%lld\n",ans);
}
return 0;
}
D题很像之前做过的一道题,C. 0689
一样的,我们强制左端点一定要改变,否则的话,贡献会在后面计算
然后对于从后往前第k个1,后面已经不会在计算了,所以一次性在此处算完后面的贡献即可,也就是这个位置可以不改变。
复杂度O(n),当时看着5000的数据范围,还以为做法假了
忘记注释文件操作,又WA一发。
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<set>
#include<queue>
#define fo(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (int (i)=(b);(i)>=(a);(i)--)
#define mk(x,y) make_pair((x),(y))
#define lc (o<<1)
#define rc ((o<<1)|1)
#define A puts("YES")
#define B puts("NO")
using namespace std;
typedef long long ll;
const int N=2e5+5;
const ll mo=998244353;
ll n,k,f[N],inv[N],ans,c0,c1,j;
char s[N];
void add(ll &x,ll y){
x=(x+y)%mo;
}
ll power(ll a,ll b){
ll t=1,y=a;
while (b){
if (b&1) t=t*y%mo;
y=y*y%mo;
b/=2;
}
return t;
}
ll F(ll n,ll m){
return f[n+m]*inv[n]%mo*inv[m]%mo;
}
int main() {
// freopen("data.in","r",stdin);
f[0]=1;
for (ll i=1;i<=5000;i++) f[i]=f[i-1]*i%mo;
inv[5000]=power(f[5000],mo-2);
for (ll i=4999;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mo;
scanf("%lld %lld",&n,&k);
scanf("%s",s+1);
int tot=0;
fo(i,1,n) if (s[i]=='1') tot++;
if (!k) {
if (tot==n) puts("1");
else puts("1");
return 0;
}
if (tot<k) {
puts("1");
return 0;
}
c0=c1=0;
j=0;
fo(i,1,n) {
while (j<n && (c1!=k || s[j+1]=='0')) {
if (s[j+1]=='1') c1++;
else c0++;
j++;
}
if (c1!=k) break;
if (j==n && s[i]=='1') {
add(ans, F(c0,c1));
break;
}
if (s[i]=='1') {
if (c0) add(ans, F(c0-1,c1));
}
else{
if (c1) add(ans, F(c0,c1-1));
}
if (s[i]=='0') c0--;
else c1--;
// printf("%lld\n",ans);
}
printf("%lld\n",ans);
return 0;
}