2019.7.8 校内测试题 连续数和

 题目

  连续数和 (num.cpp,1s,128MB)

【问题描述】:

  一个正整数有可能可以被表示为 n(10^9>=n>=2)个连续正整数之和,如:
  15=1+2+3+4+5
  15=4+5+6
  15=7+8
  根据输入的任何一个正整数,找出符合这种要求的所有连续正整数序列。

【输入文件】:

   一个正整数。

【输出文件】:

  输出符合题目描述的全部正整数序列,每行一个序列,每个序列都从该序列

的最小正整数开始、以从小到大的顺序打印。如果结 果有多个序列,按各序列
的最小正整数的大小从小到大打印各序列。此外,序列不允许重复,序列内的整
数用一个空格分隔。如果没有符合要求的序列,输出 "NONE"。

【输入输出样例】:

  num.in
    15
  num.out
    1 2 3 4 5 4 5 6 7 8
  num.in
    16
  num.out
    NONE

【数据规模】:

  6 种状态为:(000)(001)(011)(100)(110)(111)

 

 

考试得分:  100

 

 

主要算法 :  数列(等差数列)

 

 

 

题干:

    求一个连续数和为N的数,

 

 

应试策略:

  运用数学等差数列的基本方法
  思考:利用数列最长的长度n:(1+n)*n/2=连续数和,那么可以枚举数列长度
    1.枚举数列长度n,根据(a1+a1+n)*n/2=连续数和,求出a1
    2.将数列存储到一个结构体中,结构体成员有数列的第一个数a1,数列字符串
    3.由于需要字典序最小,又因为每一个数列的a1不同,那么就可以比较a1来进行排序

   代码

#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#define LL long long
#define FORa(i,s,e) for(LL i=s;i<=e;i++)
#define FORs(i,s,e) for(LL i=s;i>=e;i--)
#define gc pa==pb&&(pb=(pa=buf)+fread(buf,1,10000,stdin),pa==pb)?EOF:*pa++
#define File(name) freopen(name".in","r",stdin),freopen(name".out","w",stdout)

using namespace std;
static char buf[10000],*pa=buf,*pb=buf;
inline LL read();

LL n,cnt,ct;
struct Node{
    string s;
    int a1;
}s[50000];
string Turn_s(int x)
{
    string fs;
    fs.clear();
    while(x)
    {
        fs=char((x%10)+'0')+fs;
        x/=10;
    }
    return fs;
}
bool cmp(Node a,Node b)
{
    return a.a1<b.a1;
}
int main()
{
    File("num");
    n=read();
    cnt=-1+ceil(sqrt(4+8*n)/2);
    FORa(i,2,cnt)
    {
        if((2*n+i-i*i)%(2*i)==0)
        {
            LL a1=(2*n+i-i*i)/(2*i);
            s[++ct].s=Turn_s(a1),s[ct].a1=a1;
            FORa(j,2,i)
                s[ct].s=s[ct].s+" "+Turn_s(a1+j-1);
        }
    }
    sort(s+1,s+1+ct,cmp);
    if(ct==0) printf("NONE");
    else FORa(i,1,ct) cout<<s[i].s<<endl;
    return 0;
}
inline LL read()
{
    register LL x(0);register LL f(1);register char c(gc);
    while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;
    while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;
    return x*f;
}

 

 

 

 

 

非完美算法:  

    照搬应试策略

 

 

正解:

  模拟方法:

    照搬应试方法

  因数分解方法:
    1.设L,R,则S=(L+R)*(R-L+1)/2
    2.那么 2S=(L+R)*(R-L+1)
    3.将2S分解为两个因数的乘积形式,求出L,R

 

 

 

总结:

  1.数列的基本运算

  2.因数分解思想

 

 

 

 

 

 

posted @ 2019-07-11 20:28  SeanOcean  阅读(244)  评论(0编辑  收藏  举报