theArcticOcean

博观而约取,厚积而薄发

lightOJ 1278 Sum of Consecutive Integers(数论,数学推导)

题目:给出一个数n,求出有多少种连续整数和等于n(连续整数至少两个)。“For example, N = 15 has three solutions, (1+2+3+4+5), (4+5+6), (7+8).”

分析:n=a+(a+1)+(a+2)+(a+3)+……+(a+k-1) ==> n=(2a+k-1)/2*k ==>2n/k-k=2a-1 ==>2n/k-k是一个奇数。如果k是一个偶数,那么2n/k必是奇数,偶数/偶数=奇数,所以答案和奇因子的个数相关,如n=2*3^2*5^2.那么k可以取2和g(3),g(5)的组合乘积(一定要有2,3和5至少有一个),其中g(3)=3^0,3^1,3^2,g(5)=5^0,5^1,5^2。但是g(3)和g(5)不能同时取1.所以结果为C(3,1)*C(3,1)-1=8;按照相同的思路,如果k是一个奇数,那么2n/k必是一个偶数,偶数/奇数=偶数,那么k对应消除n的除2外的其他素因子(严格的说是其他素因子的组合),还以上一个例说明:k可以取g(3),g(5)的组合乘积,结果同为C(3,1)*C(3,1)-1。最后总结,对于n=2^a1*3^a2*5^a3*7^a4*---*pri^an,计算结果就是(a2+1)(a3+1)(a4+1)*--*(an+1)-1。

#include <iostream>
#include<cstdio>
using namespace std;
typedef long long LL;
const int maxn=1e7+5,maxn2=7e5;
int pri[maxn2];   
bool tag[maxn];
int top=0;
void getpri(){
	for(int i=2;i<maxn;i++){
		if(!tag[i])pri[top++]=i;
		for(int j=0;j<top&&i*pri[j]<maxn;j++){
			tag[i*pri[j]]=1;
			if(i%pri[j]==0)break;
		}
	}
} 
int main(int argc, char *argv[]) {
	//freopen("cin.txt","r",stdin);
	int n,i,j;
	LL t;
	getpri();
	while(cin>>n){
		for(i=1;i<=n;i++){
			scanf("%lld",&t);
			LL tmp=t,ans=1;
			int po=0;
			while(tmp%2==0){
				tmp/=2;
			}
            for(j=1;j<top&&pri[j]<=tmp;j++){
            	if(tmp%pri[j]==0){
            		po=1;
            		tmp/=pri[j];
            	    while(tmp%pri[j]==0){
            		    po++;
            		    tmp/=pri[j];
            	    }
            	    ans=ans*(po+1);
				}
            }
            if(tmp>1)ans*=2;  //有大于10^7的素因子出现,且一定只有一个. 
			printf("Case %d: %lld\n",i,ans-1);			
		}
	}
	return 0;
}




阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/theArcticOcean/article/details/46726915
文章标签: lightOJ
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭