洛谷 P1147 连续自然数和

题目描述

对一个给定的自然数MM,求出所有的连续的自然数段,这些连续的自然数段中的全部数之和为MM。

例子:1998+1999+2000+2001+2002 = 100001998+1999+2000+2001+2002=10000,所以从19982002的一个自然数段为M=10000的一个解。

输入格式

包含一个整数的单独一行给出M的值(10<M<2,000,000)。

输出格式

每行两个自然数,给出一个满足条件的连续自然数段中的第一个数和最后一个数,两数之间用一个空格隔开,所有输出行的第一个按从小到大的升序排列,对于给定的输入数据,保证至少有一个解。

题解: 首先是自己本人的极弱AC代码 相当于就是一个 模拟 

1.找出n的约数 用 n 去 ÷

2.
 1 #include<iostream>
 2 #include<cmath>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 const int range=2000010;
 7 
 8 int n,a[range],ans=0,pos=0;
 9 
10 struct node{
11     int start;
12     int end;
13 }an[2000010];
14 
15 bool cmp(node n1,node n2){
16     return n1.start<n2.start;
17 }
18 
19 int main(){
20     cin>>n;
21     for(int i=2;i<n;i++){    //范围注意
22         if(n%i==0){
23             a[ans++]=i;
24         }
25     }
26     for(int i=0;i<ans;i++){
27         if(a[i]%2==0){
28             int mi=(n-a[i])/(a[i]*2);    
29             int q=((n-a[i])%(a[i]*2));    //本来想法是 mi%2 判断是否==0 但是由于 int 已经转型了 所以重新定义了一个
30             if(a[i]-mi>=0&&a[i]+mi<=n&&q==0){
31                 an[pos].start=a[i]-mi;
32                 an[pos].end=a[i]+mi;
33                 pos++;
34             }
35         }
36         else{
37             if(n/a[i]%2==0){
38                 int q=(floor)(a[i]/2);
39                 if(q-n/a[i]-1>=0&&q+n/a[i]<=n){
40                     an[pos].start=q-n/a[i]+1;
41                     an[pos].end=q+n/a[i];
42                     pos++;
43                 }
44             }
45             else{
46                 int mi=(n/a[i]-1)/2;
47                 if(a[i]-mi<0){            //  给的测试点钟出现负数 相当于 一个abs()
48                     an[pos].start=mi-a[i]+1;  
49                 }
50                 else an[pos].start=a[i]-mi;
51                 an[pos].end=a[i]+mi;
52                 pos++;
53             }
54         }
55     }
56     sort(an,an+pos,cmp);
57     for(int i=0;i<pos;i++){
58         cout<<an[i].start<<" "<<an[i].end<<endl;
59     }
60     if(n/2+n/2+1==n) cout<<n/2<<" "<<n/2+1;    //判断 是否可以相邻两数相+
61     return 0;
62 }   

接下来是大佬代码 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int m;
 4 int main(){
 5     cin>>m;
 6     for(int k1=sqrt(2*m);k1>1;k1--)//枚举k1(注意是k1>1而不是k1>=1)
 7         if(2*m%k1==0 && (k1+2*m/k1)%2){//如果K2是整数而且与K1一奇一偶
 8             int k2=2*m/k1;
 9                 cout<<(k2-k1+1)/2<<" "<<(k1+k2-1)/2<<endl;//输出答案
10         }
11     return 0;
12 }

 

此处附大佬 blog  

https://www.luogu.org/blog/remenber/solution-p1147

侵删

 

 

转载于:https://www.cnblogs.com/jjjjjjy/p/11327071.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值