• CF1656D Kgood


    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;
    }
    
  • 相关阅读:
    Java图像处理
    Java图像处理
    Java文字图像识别(1)[88250原创]
    简单的Java图像处理程序
    英语、日语
    My First English Thread
    word的常用操作
    C++中结构体的的慨念和使用方法
    C#调用dll(C++(Win32))时的类型转换总结
    设置VS2008和IE8 调试ATL MFC ActiveX控件
  • 原文地址:https://www.cnblogs.com/dysyn1314/p/CF1656D.html
Copyright © 2020-2023  润新知