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

更新
E当时看过的人不多,直接下班了,题都没看
但其实也很水,当时看了说不定切了

首先n很小,估计是枚举状态之类的,想到这就差不多了
首先我们枚举每一个是大于还是小于
然后肯定是贪心的选,排序一下,最后判断一下是否符合假设即可
因为每一种状态都会考虑,所以不会漏解

需要注意的是ans有可能等于0,所以ans<=sum 即可更新
怎么这样的错误我都会犯啊?
另外c++格式换成vs的了,明显清晰了一些。

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#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 A puts("YES")
#define B puts("NO")

using namespace std;
typedef double db;
typedef long long ll;
const ll mo=998244353;
const int N=5e5+5;
const ll inf=1ll<<60;

int n, m, a[N], r[N], e[N],t[N];
char s[N];
int b[N][15], d[20],ans,y[N];
struct node {
	int cnt, id;
};
node c[N];
bool cmp(node a, node b) {
	return a.cnt < b.cnt;
}
void check(int s) {
	fo(i, 0, n - 1) t[i] = 0;

	fo(i, 0, n - 1) {
		fo(j, 1, m) {
			if (b[j][i]) t[i] += e[j];
		}
	}

	fo(i, 0, n - 1) {
		if (s & d[i]) {
			if (t[i] < r[i]) return;
		}
		else {
			if (t[i] > r[i]) return;
		}
	}

	int sum = 0;
	fo(i, 0, n - 1) sum += abs(t[i] - r[i]);

	if (ans <= sum) {
		ans = sum;
		fo(i, 1, m) y[i] = e[i];
	}
}
void work(int s) {
	fo(i, 1, m) {
		c[i].id = i;
		c[i].cnt = 0;
		fo(j, 0, n - 1) {
			if ((s & d[j]) && b[i][j]) c[i].cnt++;
			if (!(s & d[j]) && b[i][j]) c[i].cnt--;
		}
	}
	sort(c + 1, c + m + 1, cmp);

	fo(i, 1, m) {
		e[c[i].id] = i;
	}

	check(s);
}
void solve() {
	ans = 0;
	scanf("%d %d", &n, &m);
	fo(i, 0, n - 1) scanf("%d", &r[i]);
	fo(i, 0, n-1) {
		scanf("%s", s + 1);
		fo(j, 1, m) {
			b[j][i] = (s[j] == '1');
		}
	}

	d[0] = 1;
	fo(i, 1, 15) d[i] = d[i - 1] * 2;

	int st = (1 << n) - 1;
	fo(s, 0, st) {
		work(s);
	}

	fo(i, 1, m) printf("%d ", y[i]);
	printf("\n");
}
int main()
{

// #ifdef LOCAL
//  		freopen("in.txt", "r", stdin);
//     	freopen("out.txt", "w", stdout);
// #endif

		int T;
		scanf("%d", &T);
		while (T--) {
			solve();
			
		}
		return 0;
}

 
  


posted @ 2023-08-25 10:11  gan_coder  阅读(11)  评论(0)    收藏  举报