# 151 条题解

• @ 2021-03-17 20:15:41
``````#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <deque>
using namespace std;

namespace dts
{
int M;

void main()
{
scanf("%d",&M);
for (int i=1;i<M;i++)
for (int j=i+1,sum=i;j<M&&sum<M;j++)
{
sum+=j;
if (sum==M)
printf("%d %d\n",i,j);
}
}
};

int main()
{
dts::main();
}
``````
• @ 2020-05-22 11:16:48

一帮只会暴力试的，一点竞赛美学都没。

首先，这是个数学问题，连续自然数的和为 (首项+末项）* （项数)/2
所以结果就转换为(begin + end) * (end - begin + 1) / 2 = m
(begin + end) * (end - begin + 1) = 2 * m = A * B

将2m进行因数分解
(begin + end) * (end - begin + 1) = 2 * m = A * B

begin + end = A
end - begin + 1 = B

begin = (A - B + 1) /2
end = (A + B - 1) /2

• @ 2018-07-27 11:48:29

暴力
#include<iostream>
using namespace std;
int main()
{
long long s,k=0;
double d,S,A,B;
cin>>s;
S=s;
for(int a=2001;a>=2;a--)
{
A=a;
d=S/A;
if(a%2==1)
{
k=d;
if(d==k&&d>1&&s/a-a/2>0)
cout<<s/a-a/2<<" "<<s/a+a/2<<endl;

}

if(a%2==0)
{
k=d*100000;
if(k%100000==50000&&d>1&&s/a-a/2+1>0)
cout<<s/a-a/2+1<<" "<<s/a+a/2<<endl;
}
}

}

• @ 2017-11-08 16:17:42

这么水的吗
像滑动窗口一样的思想

``````#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<cmath>
#include<algorithm>
using namespace std;
template<class T> inline void read(T &_a){
bool f=0;int _ch=getchar();_a=0;
while(_ch<'0' || _ch>'9'){if(_ch=='-')f=1;_ch=getchar();}
while(_ch>='0' && _ch<='9'){_a=(_a<<1)+(_a<<3)+_ch-'0';_ch=getchar();}
if(f)_a=-_a;
}

int m,sum=1,l=1,r=1;

int main()
{
read(m);
while(r<m)
{
while(sum<m) sum+=++r;
if(sum==m) printf("%d %d\n",l,r);
sum-=l++;
}
return 0;
}
``````
• @ 2017-07-03 12:11:21

幸好数据小，暴力刷一遍就好了

• @ 2016-11-17 19:12:32

好像没有人用**尺取法**，那就发个题解
尺取法：像尺蠖蛾一般爬行，不断改变前后区间即可
2333~
%下面用**爆枚**与**等差数列**的。
```pascal
program hehe;
var m,t,i,n:longint;

begin
readln(m);

t:=0;

for i:=1 to m-1 do
begin
if n<=m then n:=n+i;
while n>m do
begin
n:=n-t;
inc(t);
end;

if n=m then writeln(t,' ',i);
end;
end.
```

• @ 2016-10-16 15:40:00

var i,n,o,min:longint;
procedure wrt;
begin
if n/i-trunc(n/i)=0.5 then _________________;
else o:=1;
end;
procedure wrs;
begin
min:=(n div i)-(i div 2);
end;
var big:longint;
begin
read(n);
for i:=n div 2 downto 2 do
begin
if (n mod i=0) or ((i mod 2=0) and (n mod i<>0)) then begin //判断；
o:=0;
if i mod 2=0 then wrt; //偶数
if i mod 2=1 then wrs; //奇数
_____________;
big:=min+i-1;
write(,' ',);
writeln;
end;
end;
end.
//不要依赖，剩下自己想

• @ 2016-08-23 22:04:22

枚举：var
i,j,m,sum:longint;
begin
readln(m);
for i:=1 to m do
begin
sum:=i;
for j:=i+1 to m do
begin
inc(sum,j);
if sum=m then writeln(i,' ',j);
if sum>m then break;
end;
end;
end.
数学：var
m:longint;
j,i:int64;
begin
readln(m);
i:=1;
while i<=m div 2 do
begin
j:=1-4*(-i*i+i-2*m);
if j>=0 then
begin
if (((-1+sqrt(j))/2)=trunc((-1+sqrt(j))/2)) and ((-1+sqrt(j))/2>i) then
writeln(i,' ',trunc((-1+sqrt(j))/2));
end;
inc(i);
end;
end.
用数学方法去做数越大这个被开方数就越大 算的比枚举要慢
在开始时数学方法远快于枚举
后面枚举快于数学方法
还有数学方法去做i必须是int64
i的平方的数据范围和i相同

• @ 2016-08-16 19:55:25
``````#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
long long m, ans;
void init(){
cin >> m;
}

long long sol(long long c){
long long root = (-1 + sqrt(1-4*c))/2;
if (root*root + root + c == 0) return root;
else return 0;
}

int main(){
//freopen ( "in.txt" , "r" , stdin);
init();

for (long long i = 1; i <= m/2; i++) {
if(long long j = sol(i-i*i-2*m)) {
if(j)
cout << i << " " << j << "\n";
}
}
return 0;
}
``````
• @ 2016-08-14 14:02:37

AC 150 纪念！
绝世傻题！！

• @ 2016-07-01 22:06:48

暴力搜索不超时~

附代码：
#include <cstdio>
#include <iostream>

using namespace std;

int main(){
ios::sync_with_stdio(false);
int m;
cin >> m;
for(int i = 1; i < m; i++){
int sum = 0,begin,end;
bool isget = false;
for(int j = i; ; j++){
if(sum+j == m){ isget = true; begin = i; end = j; break; }
else if(sum+j > m) break;
sum += j;
}
if(isget) cout << begin << " " << end << endl;
}

return 0;
}

• @ 2016-02-18 16:26:08

刚 绝对不超时
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <ctime>
#include <cmath>
#define N 10000
using namespace std;

int n;

int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n/i+i;j++)
if((i+j)*(j-i+1)==2*n)
printf("%d %d\n",i,j);
return 0;
}

• @ 2015-07-31 18:37:48

(n+n+x)(x+1)=2M

#include<stdio.h>
#include<math.h>
#include<stdlib.h>

main()
{
long m,x;
scanf("%ld",&m);
m*=2;
for (x=floor(sqrt(m));x>=1;x--)
if ((m%(x+1)==0)&&((m/(x+1)-x)%2==0)) printf("%ld %ld\n",(m/(x+1)-x)/2,(m/(x+1)-x)/2+x);
}

• @ 2015-07-23 14:10:39

P1302连续自然数和
Accepted记录信息
评测状态 Accepted
题目 P1302 连续自然数和
递交时间 2015-07-23 14:10:20
代码语言 C++
评测机 VijosEx
消耗时间 30 ms
消耗内存 276 KiB
评测时间 2015-07-23 14:10:23

评测结果
编译成功

测试数据 #0: Accepted, time = 0 ms, mem = 276 KiB, score = 10

测试数据 #1: Accepted, time = 0 ms, mem = 276 KiB, score = 10

测试数据 #2: Accepted, time = 15 ms, mem = 272 KiB, score = 10

测试数据 #3: Accepted, time = 0 ms, mem = 276 KiB, score = 10

测试数据 #4: Accepted, time = 0 ms, mem = 272 KiB, score = 20

测试数据 #5: Accepted, time = 15 ms, mem = 276 KiB, score = 20

测试数据 #6: Accepted, time = 0 ms, mem = 276 KiB, score = 20

Accepted, time = 30 ms, mem = 276 KiB, score = 100

代码
#include <iostream>
#include <stdio.h>
#include <math.h>

using namespace std;

int i , j;
int m;
int k;
int n;

int main()
{
scanf( "%d" , &m );
for( k = m ; k >= 1 ; k-- )
if( 2 * m % ( k + 1 ) == 0 )
{
n = ( 2 * m ) / ( k + 1 );
n -= k;
n /= 2;
if( ( 2 * n + k ) * ( k + 1 ) / 2 == m && n >= 0 )
printf( "%d %d\n" , n , n + k );
}
return 0;
}

• @ 2015-06-16 13:40:13

这道题和CERC2014的一道题很像，不同的是那道题数据很大（n<=10^9,多组数据）,我这种做法直接被卡常数卡掉，不过这道题可以过。

### Pascal Code

var
n,l,c,d,x,a,b:longint;
i:longint;
n2:int64;
begin
readln(n);
n2:=8*n;
l:=round(sqrt(n2));
for i:=l downto 1 do
if (n2 mod i=0)
then begin
c:=i;
d:=n2 div i;
if odd(c+d) then continue;
x:=(c+d) div 2;
if odd(d+1-x) then continue;
a:=(d+1-x) div 2;
if odd(x-1) then continue;
b:=(x-1) div 2;
if a=b then continue;
writeln(a,' ',b);
end;
end.

• @ 2014-11-03 22:58:41

var
a1,a2,n,m,i,j,k,s:longint;
begin
readln(m);
k:=trunc(sqrt(2*m));
for i:=k downto 1 do
if 2*m mod i=0 then
begin
a1:=2*m div i;
a2:=i;
if ((a1+a2)mod 2=1)and((a1-a2+1)div 2<>(a1+a2-1)div 2) then
writeln((a1-a2+1)div 2,' ',(a1+a2-1)div 2);
end;
end.

• @ 2014-11-03 22:59:40

var
a1,a2,n,m,i,j,k,s:longint;
begin
readln(m);
k:=trunc(sqrt(2 * m));
for i:=k downto 1 do
if 2 * m mod i=0 then
begin
a1:=2*m div i;
a2:=i;
if ((a1+a2)mod 2=1)and((a1-a2+1)div 2<>(a1+a2-1)div 2) then
writeln((a1-a2+1)div 2,' ',(a1+a2-1)div 2);
end;
end.

• @ 2014-10-03 15:13:32

不需枚举
program lianxun;
var m,i:longint;k:int64;
function solve(a:int64):int64;
var delta:int64;s:real;
begin
delta:=1-4*(a-sqr(a)-2*m);
if delta<0 then exit(0);
s:=sqrt(delta);
if trunc(s)-s<>0 then exit(0);
if trunc(s) mod 2=0 then exit(0);
exit((trunc(s)-1)div 2);
end;

begin
readln(m);
for i:=1 to m div 2 do
begin
k:=solve(i);
if k=0 then continue
else writeln(i,' ',k);
end;
end.

• @ 2014-08-19 21:42:13

测试数据 #0: Accepted, time = 0 ms, mem = 608 KiB, score = 10

测试数据 #1: Accepted, time = 0 ms, mem = 612 KiB, score = 10

测试数据 #2: Accepted, time = 0 ms, mem = 612 KiB, score = 10

测试数据 #3: Accepted, time = 0 ms, mem = 612 KiB, score = 10

测试数据 #4: Accepted, time = 0 ms, mem = 612 KiB, score = 20

测试数据 #5: Accepted, time = 0 ms, mem = 612 KiB, score = 20

测试数据 #6: Accepted, time = 15 ms, mem = 612 KiB, score = 20

Accepted, time = 15 ms, mem = 612 KiB, score = 100

今日开始刷Vj的留念！！感觉Pascal代码一长就各种恶心= =所以风格要非主流
设n=i*m，把i从2到n-1循环
如果n MOD i=0，
若i此时为奇数 说明有i个连续的整数加起来为n，就且中位数为m（要加个判断看是不是都是自然数）
若此时i为偶数且m为整数，不可能（因为偶数个连续整数中位数一定是1/2整数倍）
若此时i为偶数且m为 什么什么点5（XX.5，就是1/2整数倍），则有i个连续整数何为n，m为中位数

= =貌似有点绕，其实我自己也有点棘手，F7了半天……
那就上代码

code(pascal)：

var
n,i,m,r:longint;
f:boolean;
begin
readln(n);
for i:=trunc(n*2/3) downto 2 do
begin
if i mod 2=1then begin
m:=n div i;
if(n mod i=0)and(m-i div 2>=0)and(m+i div 2<=n)then
writeln(m-i div 2,' ',m+i div 2);
end
else begin
r:=n div i;
if((2*n)mod i=0)and(n mod i<>0)and(r-i div 2-1>=0)and(r+i div 2+1<=n)then
writeln(r-i div 2+1,' ',r+i div 2);
end;
end;
end.

• @ 2014-08-06 11:46:48

超短代码

#include <stdio.h>
int main(){
int i,k,m,sum;
scanf("%d",&m);
for(i=0;i<m;i++){
sum=0;
for(k=i;sum<m;k++) sum+=k;
if(sum==m) printf("%d %d\n",i,k-1);
}
return 0;
}

• @ 2014-01-26 14:12:58

### 枚举即可

一开始走的弯路我就不展示了
设b=a+k
所以

(2a+k)(k+1)=2m
m-k(k+1)/2=a(k+1)>0
所以
k<sqrt(2m)<2^16<40000
然后枚举k即可求a=(m-k(k+1)/2)/(k+1) (当然a得是整数吧,a要大于0吧)
注释掉的是一开始走弯路的.设的是a,b枚举的是b,b的范围比较大,肯定超时,而且每枚举一次还要开方.

#include<stdio.h>
#include<math.h>
int main()
{
unsigned long long m;
int a,b,x,k;
double xx;
scanf("%lld",&m);
xx=sqrt(m<<1); k=(int)floor(xx);
if (!(fabs(xx-k) < 1e-6)) k++;
while (k) {
if (k&1) x=((k+1)>>1)*k; else x=(k>>1)*(k+1);
x=m-x;
if (x%(k+1) == 0) {
a=x/(k+1);
b=a+k;
if (a>0)
printf("%d %d\n",a,b);
}
k--;
}
return 0;
}

ID
1302

3

(无)

2539

1289

51%

3