ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1656D K-good

2022-04-10 13:34:11  阅读:171  来源: 互联网

标签:good frac cdot CF1656D leq 正整数 define


CF1656D K-good

题目大意

题目链接

对于一个正整数 \(n​\) 和一个正整数 \(k​\),称 \(n​\) 是 \(k​\)-good 的当且仅当 \(n​\) 可以被写成 \(k​\) 个正整数之和,且这 \(k​\) 个正整数除以 \(k​\) 的余数互不相同。

\(T\) 次询问,每次给你一个 \(n\),请你求出任意一个 \(\geq 2\) 的 \(k\) 使得 \(n\) 是 \(k\)-good 的,或告知无解。

数据范围:\(1\leq T\leq 10^5​\),\(1\leq n\leq 10^{18}​\)。

本题题解

考虑 \(n​\) 是 \(k​\)-good 的条件。因为题目要求“\(k​\) 个互不相同的正整数”,那么它们至少是 \(1, 2, \dots, k​\)。因为是在 \(\bmod k​\) 意义下考虑这 \(k​\) 个正整数,所以我们还可以给其中任意一个数加上任意个 \(k​\)。所以,题目的要求等价于 \(n​\) 可以被写成这种形式:\(n = 1 + 2 + \dots + k + k \cdot m = \frac{k(k + 1)}{2} + k\cdot m​\),其中 \(m​\) 是任意非负整数。

分类讨论,先考虑 \(k\) 是偶数的情况。那么相当于 \(n = \frac{k}{2} \cdot k + \frac{k}{2} + k\cdot m = k\left(\frac{k}{2} + m\right) + \frac{k}{2}\)。进而可以拆成两个条件:

  1. \(n \bmod k = \frac{k}{2}\)
  2. \(\frac{n - \frac{k}{2}}{k} \geq \frac{k}{2}​\),即 \(n \geq \frac{k}{2}\cdot (k + 1)​\)

先考虑第 1 个条件。它相当于:\(k\) 是 \(2n\) 的约数,且不是 \(n\) 的约数。那么显然这就和 \(n\) 分解质因数后“\(2\)”的次数息息相关了。将 \(n\) 中 \(2\) 的最高次数记为 \(\nu_2(n)\)。那么第 1 个条件等价于:\(k\) 必须是 \(2^{\nu_2(n) + 1}\) 乘以一个 \(n\) 的奇约数这个形式。同时,为了满足第 2 个条件,显然 \(k\) 要越小越好。所以可以令 \(k_1 = 2^{\nu_2(n) + 1}\)。

此时检查第 2 个条件,若 \(\frac{k_1}{2} \cdot (k_1 + 1) \leq n​\),那么 \(k_1​\) 就是答案。否则说明偶数的 \(k​\) 无解,只能考虑奇数的情况。

一个巧妙的想法是,令 \(k_2 = \frac{2n}{k_1}\),显然,\(k_2\) 是一个奇数。下面我们将证明,只要 \(k_2 \neq 1\)(题目要求 \(k\geq 2\)),那么 \(k_2\) 一定是满足条件的答案。因为 \(\frac{k_1}{2} \cdot (k_1 + 1) > n\),所以 \(\frac{2n}{k_1} < k_1 + 1\),即 \(k_2 < k_1 + 1\)。又因为 \(k_2\) 是奇数,所以 \(k_2 \leq k_1 - 1\)。所以 \(\frac{k_2(k_2 + 1)}{2} \leq \frac{k_2\cdot k_1}{2} = n\)。又因为 \(n\) 是 \(k_2\) 的倍数,所以 \(n - \frac{k_2(k_2 + 1)}{2} = n - k_2\cdot\frac{k_2 + 1}{2}\) 也一定是 \(k_2\) 的倍数(即 \(k_2 \cdot m\) 的形式)。综上所述,\(k_2\) 满足所有要求。

另外,若 \(k_2 = 1​\),则一定无解。因为前面已经说过,\(k​\) 只能是奇数。同时,\(n​\) 显然又必须是 \(k​\) 的倍数。而 \(k_2 = 1​\) 意味着 \(n​\) 是 \(2​\) 的整数次幂,它没有其它奇约数。所以此时输出 \(-1​\) 即可。

单次询问时间复杂度 \(\mathcal{O}(\log_2 n)\),总时间复杂度 \(\mathcal{O}(T\cdot \log_2n)\)。

参考代码

// problem: CF1656D
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define mk make_pair
#define lob lower_bound
#define upb upper_bound
#define fi first
#define se second
#define SZ(x) ((int)(x).size())

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

template<typename T> inline void ckmax(T& x, T y) { x = (y > x ? y : x); }
template<typename T> inline void ckmin(T& x, T y) { x = (y < x ? y : x); }

void solve_case() {
	ll n;
	cin >> n;
	
	int v = 1;
	while (n % (1LL << v) == 0)
		++v;
	
	ll k1 = (1LL << v);
	if (n * 2 / k1 >= k1 + 1) { // 等价于 (k1 * (k1 + 1) / 2 <= n),这样写防止爆 long long
		cout << k1 << endl;
		return;
	}
	
	int k2 = n * 2 / k1;
	if (k2 == 1) {
		cout << -1 << endl;
		return;
	}
	cout << k2 << endl;
}

int main() {
	int T;
	cin >> T;
	while (T--) {
		solve_case();
	}
	return 0;
}

标签:good,frac,cdot,CF1656D,leq,正整数,define
来源: https://www.cnblogs.com/dysyn1314/p/CF1656D.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有