Codeforces Round #729 (Div. 2)

A. Odd Set

You are given a multiset (i. e. a set that can contain multiple equal integers) containing 2n integers. Determine if you can split it into exactly n pairs (i. e. each element should be in exactly one pair) so that the sum of the two elements in each pair is odd (i. e. when divided by 2, the remainder is 1).

Input
The input consists of multiple test cases. The first line contains an integer t (1≤t≤100) — the number of test cases. The description of the test cases follows.
The first line of each test case contains an integer n (1≤n≤100).
The second line of each test case contains 2n integers a1,a2,…,a2n (0≤ai≤100) — the numbers in the set.

Output
For each test case, print “Yes” if it can be split into exactly n pairs so that the sum of the two elements in each pair is odd, and “No” otherwise. You can print each letter in any case.

  • 思路:水题,判断奇数偶数出现的次数是否一致即可

  • 代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll N = 1e6 + 10, mod = 1e9 + 7;
ll t, n, m, x[N];
inline void solve() {
	cin >> n;
	ll s1 = 0, s2 = 0;
	for(int i = 1; i <= n * 2; i++) {
		cin >> m;
		if(m & 1) s1++;
		else s2++;
	}
	if(s1 == s2) cout << "Yes" << endl;
	else cout << "No" << endl; 
	return ;
}
int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> t;
	while(t--) {
		solve();
	}
	return 0;
}

B. Plus and Multiply

There is an infinite set generated as follows:

1 is in this set.
If x is in this set, x⋅a and x+b both are in this set.
For example, when a=3 and b=6, the five smallest elements of the set are:

1,
3 (1 is in this set, so 1⋅a=3 is in this set),
7 (1 is in this set, so 1+b=7 is in this set),
9 (3 is in this set, so 3⋅a=9 is in this set),
13 (7 is in this set, so 7+b=13 is in this set).
Given positive integers a, b, n, determine if n is in this set.

Input
The input consists of multiple test cases. The first line contains an integer t (1≤t≤105) — the number of test cases. The description of the test cases follows.

The only line describing each test case contains three integers n, a, b (1≤n,a,b≤109) separated by a single space.

Output
For each test case, print “Yes” if n is in this set, and “No” otherwise. You can print each letter in any case.

  • 题意:给出一个无穷集合,集合中的初始值只有1,可以进行以下操作

    • 如果x在集合中,那么x * a和x + b也在集合中
    • 给出n, a, b,求n是否在集合中。
  • 思路:对于一个数x,如果(n - x) % b == 0,那么我们就可以通过进行若干次的+b操作得到x,所以我们只需要判断是否存在一个数使得n % b == x % b,对于a操作,得到的余数就是x的余数a,而+b操作则不影响余数,所以我们可以通过枚举1*a,来判断是否存在x

  • 代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
	ll t; cin >> t;
	while(t--) {
		ll n, a, b; cin >> n >> a >> b;
		ll mod = n % b;
		ll flag = 0;
		for(ll i = 1; i <= n && !flag; i *= a) {
			if(i % b == mod) {
				flag = 1; break;
			}
			if(a == 1) break;
		}
		if(flag) cout << "Yes" << endl;
		else cout << "No" << endl;
	}	
	return 0;
} 

C

Let f(i) denote the minimum positive integer x such that x is not a divisor of i.

Compute modulo 109+7. In other words, compute f(1)+f(2)+⋯+f(n) modulo 109+7.

Input
The first line contains a single integer t (1≤t≤104), the number of test cases. Then t cases follow.

The only line of each test case contains a single integer n (1≤n≤1016).

Output
For each test case, output a single integer ans, where ans= modulo 109+7.

  • 题意:函数f[i]代表不能整除i的最小正整数,求f[1] + …… + f[n]

  • 思路:观察数据n<1e16,可知需要先打表找到一个规律。

  • 打表代码

inline void solve() {
	for(int k = 1; k <= 100; k++) {
		ll ans;
		for(int i = 1; i <= k + 1; i++) {
			if(k % i != 0)  {
				ans = i;
				break;
			}
		}
		f[k] = f[k - 1] + ans % mod;
		cout << k << " -> " << ans % mod << endl; 
	}
	return ;
}
  • 观察打表结果,可以发现

    • 对于每一个x,其贡献最少为2
    • 而第一个出现3的位置是2,第一个出现4的位置是6,第一个出现5的地方是12,由此可见,第一次出现x的位置是1~x-1的最小公倍数
  • 然后就可以开始猜了,首先明确每个i的贡献最少为2,然后对于2的倍数,那么2就不可取,贡献加1,对于6的倍数,3不可取,贡献再加1,对于12的倍数,4不可取,贡献再加1,以此类推……

  • 于是我们可以先打表,对于k:143,求出1k-1的最小公倍数,如果数x想要有calc[k]的贡献,那么它一定是calc[k]的倍数,我们可以通过x/calc[k]得到x中包含calc[k]的倍数的个数,其个数便是在原有基础上再+1的贡献值,最后相加即可

for (int i=3;i<=43;i++) ans=(ans+n/calc[i])%1000000007;

这句代码的大意是,从k = 3开始,判断n中有多少个数是1~k - 1的倍数,假如有x个数是,那么这x个数的贡献就多1,所以是+上了n/calc[i],比如对于n = 12时,calc[3] = 2,calc[4] = 6, calc[5] = 12,所以贡献就是2 * 12 + 12/2 + 12/6 + 12/12,分别对应,4、8、10的贡献+1 = 3,6的贡献+2 = 4、12的贡献+3 = 5,其余都是2

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll N = 1e6 + 10, mod = 1e9 + 7;
ll t, x[N], f[N];
inline void solve() {
	ll n, ans = 0; cin >> n;
	ans = n * 2;
	for(int i = 3; i <= 42; i++) ans = (ans + n / x[i] + mod) % mod;
	cout << ans << endl;
	return ;
}
int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	x[1] = x[2] = 2;
	for(ll i = 3; i <= 42; i++)	{
		x[i] = x[i - 1] * (i - 1) / __gcd(i - 1, x[i - 1]);
	}
	cin >> t;
	while(t--) {
		solve();
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顶白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值