JZOJ5773简单数学题 题解

题目描述

Description
话说, 小X是个数学大佬,他喜欢做数学题。有一天,小X想考一考小Y。他问了小Y一道数学题。题目如下:
对于一个正整数N,存在一个正整数T(0<T<N),使得(n-t/2)/(n-t)的值是正整数。
小X给出N,让小Y给出所有可能的T。如果小Y不回答这个神奇的大佬的简单数学题,他学神的形象就会支离破碎。所以小Y求你帮他回答小X的问题。
Input
一个整数N。
Output
第一个数M,表示对于正整数N,存在M个不同的正整数T,使得是整数。后面是M个数,每一个数代表可能的正整数T(按从小到大的顺序排列)。
Sample Input1:
1
Sample Input2:
3
Sample Input3
180
Sample Output
0
Sample Output
1 2
Sample Output
5 120 144 160 168 176
Data Constraint
对于5%的数据,N=1.
对于20%的数据,N<=5.
对于40%的数据,N<=1000000
对于另外20%的数据,答案只有1个,且N为质数,保证对于前60%的数据,当N为质数的时候,答案都一定只有一个,对于这20%的数据,满足2<N。
对于80%的数据,N<=10^9.
对于100%的数据,N<=10^14.

分析

一道数论题,我们可讲其化简,可得1+t/(2*n-2*t),因为1是整数,所以我们要保证t/(2*n-2*t)是整数,设这个整数是k,可得(2*k+1)/2*k=n/t,因为2*k+1与2*k互质,所以此时得n/t是一个最简分数,此时及枚举n的所有奇因数,若满足条件,则将其添加到答案序列。所以我们可想到一个做法,枚举小于sqrt(n)的所有奇数,若是n因子,则对其进行讨论,若n/i是奇数,则将(n/i-1)*i,及n-i放入,同理,此时也要处理n/i,处理方法相同,所以可在O(sqrt(n))的时间里a掉它,注意开long long,n要开,枚举的i也要开!!!
上代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,k,al[10000],ans=0;
int main(){
    freopen("math.in","r",stdin);
    freopen("math.out","w",stdout);
    memset(al,0,sizeof(al));
    scanf("%lld",&n);
    for(long long i=1;i*i<=n;i++){
        if(n%i==0){
            if((n/i)%2){
                ll m=n-i;
                if(m)
                    al[++ans]=m;

            }
            if(i%2){
                ll m=n-n/i;
                if(m)
                    al[++ans]=m;
            }
        }
    }
    sort(al+1,al+1+ans);
    printf("%lld ",ans);
    for(int i=1;i<=ans;i++)
        printf("%lld ",al[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sjzezwzy/article/details/81511602