2021-08-16 SSL 模拟赛 T3
题目大意:
求出 1 − n − 1 1-n-1 1−n−1 中所有满足 n − 0.5 x n − x = k , k ∈ N ∗ \frac{n-0.5x}{n-x}=k,~~k\in N* n−xn−0.5x=k, k∈N∗ 的 x x x。
思路:
我们来转化一下这个公式,让它变得好看一点:
n
−
0.5
x
n
−
x
=
2
n
−
x
2
n
−
2
x
=
k
\frac{n-0.5x}{n-x}=\frac{2n-x}{2n-2x}=k
n−xn−0.5x=2n−2x2n−x=k
移项得到:
2
n
−
x
=
n
+
(
n
−
x
)
=
k
(
2
n
−
2
x
)
=
2
k
(
n
−
x
)
2n-x=n+(n-x)=k(2n-2x)=2k(n-x)
2n−x=n+(n−x)=k(2n−2x)=2k(n−x)
然后左边只保留
n
n
n :
n
=
(
2
k
−
1
)
(
n
−
x
)
n=(2k-1)(n-x)
n=(2k−1)(n−x)
所以就有
(
n
−
x
)
(n-x)
(n−x)是
n
n
n 的约数。
然后我们可以在
O
(
n
)
O(\sqrt n)
O(n) 的时间复杂度内求出
n
n
n 的所有约数并且求出
x
x
x
注意
n
/
(
n
−
x
)
=
2
k
−
1
n/(n-x)=2k-1~~~~
n/(n−x)=2k−1
2
k
−
1
2k-1
2k−1 是奇数,这是另一个约束条件。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
#define r register
#define rep(i,x,y) for(r ll i=x;i<=y;++i)
#define per(i,x,y) for(r ll i=x;i>=y;--i)
using namespace std;
typedef long long ll;
const ll V=1e7+10;
ll n,top,a[V],now;
ll ans[V],cnt;
void cut()
{
rep(i,1,now)
if(n%i==0)
{
a[++top]=i;
ll x=n/i;
if(i!=x) a[++top]=n/i;
}
}
void put(ll x)
{
if(x<0) putchar('-'),x*=-1;
if(x>9) put(x/10);
putchar(x%10+48);
}
int main()
{
scanf("%lld",&n);
now=sqrt(n);
cut();
sort(a+1,a+top+1,greater<ll>());
rep(i,1,top)
if(n-a[i]>0)
if((n/a[i])&1)
ans[++cnt]=n-a[i];
put(cnt);
putchar(' ');
rep(i,1,cnt)
put(ans[i]),putchar(' ');
return 0;
}