题解 [CF1656D] K-good

传送门

个人感觉还是挺有思维难度的

首先发现 \(n\) 为奇数时答案为 2
然后发现就是要找

\[n\equiv 0\pmod k(2\nmid k) \]

\[n\equiv \frac{k}{2}\pmod k(2\mid k) \]

同时还要满足 \(\frac{k(k+1)}{2}\leqslant n\),称为条件 1
打表发现 \(n=2^t\) 时无解
然后就只会到根号复杂度了

正解感觉是个无意义比较巧合的结论
考虑 \(\max \{t\mid 2^t|n\}\)
若这个 \(2^t\) 满足条件 1,那么输出即可
否则考虑 \(k_2=\frac{n}{2^{t-1}}=\frac{2n}{k_1}\),令 \(k_1=2^t\)
\(\frac{k_1(k_1+1)}{2}> n\),那么移项得 \(k_2<k_1+1\),而 \(k_2\) 为奇数,所以 \(k_2<k_1\)
发现 \(\frac{k_2(k_2+1)}{2}\leqslant \frac{k_2k_1}{2}=n\)
所以这个 \(k_2\) 一定合法,输出即可
并不知如何找到这样的性质

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n;

signed main()
{
	int T=read();
	while (T--) {
		n=read();
		if (__builtin_popcountll(n)==1) {puts("-1"); continue;}
		__int128 i=2;
		while (n%i==0) i<<=1;
		if (i*(i+1)/2<=n) printf("%lld\n", (ll)i);
		else printf("%lld\n", (ll)(2*n/i));
	}

	return 0;
}
posted @ 2022-03-29 19:26  Administrator-09  阅读(1)  评论(0编辑  收藏  举报