Little Difference

解决一道算法题,寻找将正整数n分解为若干个相邻整数乘积的所有可能方式,并统计这些解的数量。对于特殊情形,如n为2的幂时,提供了一种高效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Little Difference

时间限制: 3 Sec  内存限制: 512 MB

题目描述

Little Lidia likes playing with numbers. Today she has a positive integer n, and she wants to decompose it to the product of positive integers.
Because Lidia is little, she likes to play with numbers with little difference. So, all numbers in decomposition should differ by at most one. And of course, the product of all numbers in the decomposition must be equal to n. She considers two decompositions the same if and only if they have the same number of integers and there is a permutation that transforms the first one to the second one.
Write a program that finds all decompositions, which little Lidia can play with today.

输入

The only line of the input contains a single integer n (1≤n≤1018).

输出

output the number of decompositions of n, or -1 if this number is infinite.

样例输入

12

样例输出

3


题目大意:给定一个正整数n,如果k1个a和k2个(a+1)相乘正好等于n,则为一个解,输出解的个数,如果有无数个解则输出-1。


一个非常low的解法:如果暴力求解sqrt(1e18)的范围肯定会超时。但如果k1+k2==n的话,则a一定等于(int)sqrt(n),将这种情况特判掉,则(k1+k2)>=3,所以a不会超过三次根号下1e18,这时候暴力一波也不会超时了。特殊情况:如果n是2的次幂,则n可以写成k个2与无数个1的乘积,故有无数多个解。(注意:n本身也是一个解)


#include <bits/stdc++.h>
int main()
{
    long long n, m, i, ans, flag, j;
    ans = flag = j = 1;
    scanf("%lld", &n);
    for (i = 0; i <= 64; i++)
    {
        if (j == n)
        {
            flag=0;
            break;
        }
        j *= 2;
    }           //判断n是不是2的次幂
    if (!flag)
        puts("-1");
    else
    {
        long long tmp = (long long) sqrt(n);
        if (tmp * tmp == n || tmp * tmp + tmp == n)
            ans++;          //特判(k1+k2==2)的情况
        m = std::min((long long) pow(n, 1.0 / 3) + 1, tmp - 1);         //确定暴力的范围
        for (i = 2; i <= m; i++)
        {
            long long k = n;
            while (k % i == 0)
                k /= i;
            if (k == n)
                continue;       //如果(i+1)的k次方等于n,则下次循环i+1后会重复计数,故需防止重复计数
            while (k % (i + 1) == 0)
                k /= (i + 1);
            if (k == 1)
                ans++;
        }
        printf("%lld\n", ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值