Codeforce #828 div3

说下昨晚的心路历程吧,本来想着要好好打一场div3的,然后8点多开始就闲着没事干,闲不住就打无限火力去了,然后打过头差点忘记比赛了,开始了得十分钟才开始写第一道题TvT

A题模拟(大水题):

大概题意是给你一组数和一个字符串,询问是否能用相应位置的字符替换掉数组中的数,对于相同的数字,其对于字符也应相同,

看了下数据挺水O(n^2)随便搞一搞就行

void solve()
{
	int n; cin >> n;
		char s[100];
		int tt[100];
		for (int i =0; i < n; i ++) cin >> tt[i];
		cin >> s;
		bool flag =true;
		for (int i = 0; i < n; i ++) {
			for (int j = 1; j < n; j ++) {
				if (tt[i] == tt[j]) {
					if (s[i] != s[j]) {
						puts("NO");
						return;
					}
				}
			}
		}
	 puts("YES");
}

B题模拟(也是大水题):

大概题意是给你n个数q个询问,两种模式,0是让偶数全部加上x,1让奇数全部加上x

看了眼数据估计会爆int直接用long long了,然后1e5肯定不能直接O(n^2)暴力

这里可以利用一个性质,在读入数组的时候先开个计数器统计偶数的数量(奇数n-cnt就可以了)

然后搞一个sum统计数组和,每次询问的时候只需要sum + x*相应的个数就可以了

void solve()
{
	int n, q; scanf("%d %d",&n,&q);
	int cnt = 0;
	ll sum = 0;
	for (int i = 1; i <= n; i ++) {
		int x;
		scanf("%d",&x);
		if (x%2==0) cnt ++;
		sum += x;
	}
	while (q --) {
		int tp, x;
		scanf("%d %d",&tp, &x);
		if (tp == 0) {
			sum = sum + x*cnt;
			if (x%2==1)
				cnt = 0;
			printf("%lld\n",sum);
		}
		else {
			sum = sum + x*(n-cnt);
			if (x%2==1)
				cnt = n;
			printf("%lld\n",sum);
		}
	}
}

C题模拟(个人感觉是最水的一道题了):

大概题意就是给你个字符串表示红绿黄灯的情况,但不告诉你当前是什么时刻,你只知道当前的信号灯的状态,问你何时是能保证过马路的最小时间

这题可以先把字符串变成两倍然后倒着找给定信号灯与绿灯之间的距离,每次找到绿灯就记录下来,找到c就减一下取个最大值

void solve()
{
	char c;
	char s[N];
	int n; cin >> n >> c;
	cin >> s+1;
	for (int i = 1; i <= n; i ++)
		s[i+n] = s[i];
	int last = INF; 
	int ans = -1;
	for (int i = 2*n; i >= 1; i --) {
		if (s[i] == 'g') last = i;
		if (i <= n && s[i] == c) {
			ans = max(ans,last-i);
		}
	}
	cout << ans << endl;
}

D题数学(比较有意思的一道题了):

大概题意是给你n个正整数的连乘,再给定一个操作,这个操作可以将ai替换成ai*i,问你最少操作多少次这n个数的连乘可以被2^n整除

因为这题是连乘积嘛,所以说只要这n个数的连乘积最终里面2的数量大于等于n就可以被

2^n整除,我的想法是类似于快速幂的思想,对于每个ai看一下里面有多少个2,对于i也执行相同的操作,如果是ai中2的数量小于2再考虑替换,因为要求最小操作数,所以对于i我们从大到小看,每次加一下,直到大于等于n,如果最后还是小于的话就不能被整除,输出-1即可

int find(int x)
{
	int res = 0;
	while (x%2==0) {
		x >>= 1;
		res ++;
	}
	return res;
}
void solve()
{
	int n; cin >> n;
	vector<int> a(n+10);
	priority_queue<int> pq;
	int cnt = 0;
	for (int i = 1; i <= n; i ++) {
		cin >> a[i];
		cnt += find(a[i]);
		pq.push(find(i));
	}
	int ans = 0;
	while (cnt < n) {
		if (pq.empty()) break;
		cnt += pq.top(); pq.pop();
		ans ++;
	}
	if (cnt < n) 
		cout << -1 << endl;
	else
		cout << ans << endl;	
}

E题(也是道数学题):

e题一开始做的时候我是一点思路没有,首先直接暴力写的话肯定会TLE,本着快乐生活的态度,这题没写完我就上床睡觉去了,白天醒了才把这题补完。

首先本题题意是给定两个区间a<x<=c,b<y<=d,问你能否确定x,y的值使得a*b|x*y,不存在则输出-1 -1

首先我就傻乎乎的写了个二重循环直接暴力查找,打算把E1过了就睡觉的,很快啊,TLE,果然不出所料。所以直接找是肯定不可能的了,namo,我们该怎么办呢,我们可以想到,如果一个数可以被另一个数整除的话,那么这个数的因子肯定也可以被另一个数整除,我们可以先把a和b分割成几个因子,然后分别给这两个因子加上1,本质还是枚举,不过枚举的范围大大缩小了(至少肯定能过这题)

void solve()
{
	ll a, b, c, d;
	cin >> a >> b >> c >> d;
	vector<ll> p1, p2;
	for (int i = 1; i <= a/i; i ++) {
		if (a%i==0) {
			p1.push_back(i);
			if (i != a/i) p1.push_back(a/i);
		}
	}
	for (int i = 1; i <= b/i; i ++) {
		if (b%i==0) {
			p2.push_back(i);
			if (i != b/i) p2.push_back(b/i);
		}
	}
	for (ll q1 : p1) {
		for (ll q2 : p2) {
			ll t1 = q1 * q2;
			ll t2 = a*b / q1 / q2;
			ll d1 = a / t1 + 1;
			ll d2 = b / t2 + 1;
			if (t1*d1 <= c && t2*d2 <= d) {
				cout << t1*d1 << ' ' << t*d2 << endl;
				return;
			}
			d1 = b / t1 + 1;
			d2 = a / t2 + 1;
			if (t1*d1 <= d && t2*d2 <= c) {
				cout << t2*d2 << ' ' << t1*d1 << endl;
				return;
			}
		}
	}
	cout << -1 << ' ' << -1 << endl;
}

F题嗷嗷待哺ing。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值