UPC13522 Favourite Number
Favourite Number
时间限制: 1 Sec 内存限制: 128 MB提交: 6 解决: 4
[提交] [状态] [命题人:admin]
题目描述
Volodymyr’s favourite number is A and it has an odd number of positive divisors. When you add K to this number, the resulting sum also has an odd number of positive divisors. Given K, find all possible values of A, Volodymyr’s favourite number.
输入
The only line of input contains K, a positive integer not exceeding 109.
输出
On the first line, print the number of possible values of A. On the second line, print all possible values of A in ascending order, separated by a single space.
样例输入
1
样例输出
0
提示
Note that since zero has infinitely many divisors, it cannot be classified as a number with an odd number of divisors.
比较基础的数论题目。
题目大意,找到所有的含有奇数个因子的数a,使得a+k也含有奇数个因子。
由约数基本定理,对于一个数n=(p1^a1)*(p2^a2)*(p3^a3)......(ps^as)
其约数个数为num=(a1+1)*(a2+1)*(a3+1)......(as+1)
所以很显然就看出来了,含有奇数个因子的数,其所有质因数的指数必然是偶数,也就等价于这个数是完全平方数。
设 a=n*n 于是问题就转化成了求 一个n 使得 |n*n| + k = |m*m|
去掉这个式子的绝对值,就会得到以下三种情况。
(1)n*n+k=m*m 此时我们思考一个问题,什么样的k能使n*n+k=m*m,由完全平方公式,当k=2*i*n+i*i的时候,n*n+k=(n+i*k)^2 此时的(n+i*k)即为m。
继续化简得到 n = (k-i*i)/(2*i) 。这些自然都需要是整数域的运算,所以2*i为(k-i*i)的因数,
我们就可以根号k的复杂度枚举i,然后判断是否满足(k-i*i)整除 2*i 即可,于是此时得到的n*n即为答案之一。
(2)-(n*n)+k = -(m*m) 这种情况和上面的类似,n*n-k=m*m,然后不同的是 k=2*i*n - i*i ,得到 n*n - k = (n-i*k)^2。
然后就和(1)一样判断是否整除即可,-(n*n)即为答案。
(3) - (n*n)+k = m*m 这种情况是最好判断的,直接根号k的复杂度暴力判断找到n即可。
最后需要注意的是,每一步我们找到的n*n和k+n*n不能是0,每一步都要判一下。
总体分析完以上三种情况,放进一个set里去重加排序(真省心啊),然后输出答案即可,时间复杂度为根号k。
AC代码
#include <bits/stdc++.h> typedef long long ll; using namespace std; set<ll>s; int main() { ll n,x,y; scanf("%lld",&n); for(int i=1;i*i<=n;i++) { if((n-i*i)%(2*i)==0) { x=((n-i*i)/(2*i))*((n-i*i)/(2*i)); if(x!=0&&(x+n)!=0)s.insert(x); } if((n+i*i)%(2*i)==0) { x=((n+i*i)/(2*i))*((n+i*i)/(2*i)); if(x!=0&&(n-x)!=0)s.insert(-x); } x=n-i*i;y=sqrt(x+0.5); if(y*y==x&&y!=0)s.insert(-(i*i)); } int len=s.size(); printf("%d\n",len); for(ll t:s)printf("%lld ",t); if(len>0)puts(""); return 0; }