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的方案数,一看到连续序列和,等差数列求和公式一定没跑。假设连续区间为[L,R] ,则根据题意:
(L+R)*(R-L+1) =2*N
令 a = (L+R)
令 b=(R-L+1)
a*b=2*N (a 和 b 我们可以枚举 2*N的因子得到 )
我们可以解出
L=(a-b+1) /2
R=(a+b-1)/2
然后因为a和b我们可以通过枚举因子得到,然后问题就解决了,但是看了下时间复杂度,枚举因子sqrt(2*n) *T 肯定超时。
只能再化简一下了,我们要求的L和R 一定要是整数,a和b什么情况下才可以满足呢?我们发现a和b一个是偶数一个是奇数一定可以满足这个条件。
但是怎么知道 2*N可以分解为多少个 奇数*偶数呢? 这里我们可以通过 算数基本定理来考虑,假设N*2=p1^ r1 p2^r2 p3 ^r3….pk^rk (分解整数的时间复杂度为o ( n ^ ( 1 / 4 ) ) )
要想分解为偶数*奇数,那么我们可以发现,偶数一定是由质因子2来提供的,我们把2^r 看做一个整体,从后面的部分中挑出一个因子 来和2^r组成一个数,剩下的部分为一个数字,那么前一个数一定为偶数,后一个数一定为奇数。(这里的通过质因子分解 ,来划分为两个数字,是一种组合在里面,如果不理解的话,可以找找规律)
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N = (int)1e7+11;
const int M = 1e6+11;
const int mod = 1e9+7;
const int inf =0x3f3f3f3f;
bool su[N+1]={1,1,0};int prm[664579+11],sz; // prm如果也开1e7的话 会MLE
void init(){
for(LL i=2;i<N;i++){
if(!su[i]){
prm[sz++]=i;
for(LL j=i*i;j<N;j+=i){
su[j]=1;
}
}
}
// cout<<sz<<endl;
}
int main(){
init();
int cas=1;
int T ;scanf("%d",&T);
while(T--){
LL n;scanf("%lld",&n);
LL m=n;
LL a=0,b=1; n*=2;
for(LL i=0;prm[i]*1ll*prm[i]<=n&&i<sz;i++){
if(n%prm[i]==0){
int cnt=0;
while(n%prm[i]==0){
cnt++;
n/=prm[i];
}
if(i==0) {
a=cnt;
continue;
}
b*=(cnt+1);
}
}
if(n!=1) b*=2;
LL ans;
if(a==0 || 1==b) ans=1;
else ans=b;
printf("Case %d: %lld\n",cas++,ans-1);// 因为多算了 一个 (2*N ,1) 这个组合,所以要减去
}
return 0;
}