推公式的毒瘤题
看他给的这个公式 (n-t/2)/(n-t)∈(正整数)
我们转化一下
(n-t/2)/(n-t)=x -> (n-t+t/2)/(n-t)=x -> (t/2)/(n-t)=x-1
t/(n-t)=2*(x-1) -> t=2*(x-1)*(n-t) -> t=2*(x-1)*n-2*(x-1)*t
t*(1+2*(x-1))=2*(x-1)*n -> t=(2*(x-1)*n)/(2*x-1) -> t=( ((x-1))/(2*x-1) ) *2*n
好了,由最后这个式子我们可以发现2*(x-1)不可能是2*x-1的倍数,所以t要是正整数,那么2*x-1一定是2*n的因数,并且它一定是奇数,然后我们就可以通过枚举它的奇数因子来得到答案,之后发现这样好像很慢?
然后我们想一想求因子的过程,小于sqrt(2*n)的因子,n除以它会得到大于sqrt(2*n)的因子,同理这个题也可以,于是我们就可以sqrt(2*n)的得到结果,时间复杂度上允许
然后看一看上面的式子怎么化简,
设当前枚举的奇数为i,那么i=2*x-1 那么2*(x-1)=i-1,那么t=(i-1)*(n/i)化简得到t=n-n/i
假如当前枚举到的数i并且它关于sqrt(2*n)的对称因子是奇数,那么令对称因子为2*n/i,和上面的同理,一样的转化,最后得到t=n-i/2
之后发现这样输出的话不满足题意的顺序,所以开一个优先队列,将求出来的t乘-1丢进去,然后最后输出时再乘-1就行了
记得开long long
代码
//By AcerMo
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lli long long int
using namespace std;
lli n;
priority_queue<lli>q;
signed main()
{
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
cin>>n;
if (n==1) return puts("0"),0;
for (lli i=1;i*i<2*n;i++)
{
if (2*n%i) continue;
if (i%2&&(n-n/i)&&!(2*n%i)) q.push(n/i-n);
if ((2*n/i)%2!=0&&(n-i/2)) q.push(i/2-n);
}
cout<<q.size()<<" ";
while (q.size()) cout<<-q.top()<<" ",q.pop();
return 0;
}