Given an integer N, you have to find the number of ways you can express N as sum of consecutive integers. You have to use at least two integers.
For example, N = 15 has three solutions, (1+2+3+4+5), (4+5+6), (7+8).
Input
Input starts with an integer T (≤ 200), denoting the number of test cases.
Each case starts with a line containing an integer N (1 ≤ N ≤ 1014).
Output
For each case, print the case number and the number of ways to express N as sum of consecutive integers.
Sample Input
5
10
15
12
36
828495
Sample Output
Case 1: 1
Case 2: 3
Case 3: 1
Case 4: 2
Case 5: 47
题目大意:给你一个数n,n可以表示为几个连续的数之和,最少两个数,问有多少种
比如: 15=1+2+3+4+5=4+5+6=7+8,所以有三种
解题思路:设n=a1+a2+a3+……+am,即n可以表示为m个连续的数之和,因为等差数列公差为1,所以am=a1+m-1;
所以n=m*(a1+a1+m-1)/2,即2a-1=2n/m-m------->a1=n/m-(m-1)/2,因为a1和m,n都是整数,所以n%m=0,(m-1)%2=0;
所以m为n的因子,并且是奇数,所以n的一个奇因子对应一种方案,即只需求n的奇因子个数即可,可以使用算术基本定理将n分解成有限的素数的乘积,求一个数的因子个数是所有素数因子的幂+1,相乘起来就是,那么素数只有2是偶数,
所以奇数因子的个数就是所有 素数因子(除2之外)+1的乘积,,m至少为2,即m一定要大于1,所以要减去1,除去因子1的情况
算术基本定理参考博客:https://blog.csdn.net/qq_40707370/article/details/82534085
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=1e7+10;
bool vis[maxn];
int prime[maxn/10],top;
void get_prime()//素数打表
{
top=0;
memset(vis,0,sizeof(vis));
for(int i=2;i<maxn;i++)
{
if(!vis[i])
{
prime[top++]=i;
for(int j=i+i;j<maxn;j+=i)
vis[j]=1;
}
}
}
int main()
{
get_prime();
int t;
long long n;
cin>>t;
for(int kase=1;kase<=t;kase++)
{
int ans=1;
cin>>n;
while(n%2==0)//素因子2不计数
n/=2;
for(int i=1;i<top&&prime[i]*prime[i]<=n;i++)
{
int cnt=0;
if(n%prime[i]==0)
while(n%prime[i]==0)
{
cnt++;
n/=prime[i];
}
ans*=(cnt+1);
}
if(n!=1)//因子可能大于根号n,这一步加上,幂为1,所以乘2
ans*=2;
printf("Case %d: %d\n",kase,ans-1);
}
return 0;
}