尺取 POJ - 2100

题目链接:

[https://vjudge.net/contest/279018#problem/B ]
[http://poj.org/problem?id=2100]

题面

King George has recently decided that he would like to have a new design for the royal graveyard. The graveyard must consist of several sections, each of which must be a square of graves. All sections must have different number of graves. After a consultation with his astrologer, King George decided that the lengths of section sides must be a sequence of successive positive integer numbers. A section with side length s contains s 2 graves. George has estimated the total number of graves that will be located on the graveyard and now wants to know all possible graveyard designs satisfying the condition. You were asked to find them.
输入
Input file contains n — the number of graves to be located in the graveyard (1 <= n <= 10 14 ).
输出
On the first line of the output file print k — the number of possible graveyard designs. Next k lines must contain the descriptions of the graveyards. Each line must start with l — the number of sections in the corresponding graveyard, followed by l integers — the lengths of section sides (successive positive integer numbers). Output line’s in descending order of l.
输入样例
2030
输出样例
2
4 21 22 23 24
3 25 26 27

题意

翻译一下大概就是:给你一个数,让你找到一系列连续的整数;使得数的平方的和等于这个数。然后输出的时候先输出有多少个一系列的数,再输出每个有多少个数 再输出这些数 (有点绕口 看样例就懂了)
所谓尺取就是有两个指示器i,j一开始都指向第一个,然后j往后挪到达某个条件时i往后挪,(这一题的条件就是区间内的平方和是否等于该数,小了挪j,大了挪i,相等了记录)然后再j往后挪直到遍历到上限。复杂度是O(n)。有点抽象,上代码吧。

代码

#include <stdio.h>
typedef long long ll;
struct NODE{//开的结构体记录区间
	int i,j;
}n[100000];
int main(){
	ll i,j,x,sum,flag;
	int num;
	scanf("%lld",&x);
	for(sum=num=0,i=j=1;i*i<=x;j++){
		sum+=j*j;
		if(sum==x){
			n[num].i=i;
			n[num++].j=j;
		}
		if(sum>x){
			while(i<=j){
				if(sum<x) {
					i--;
					sum+=i*i;
					break;
				}
				sum-=i*i;
				i++;
				//printf("%d %d %lld %lld\n",i,j,x,sum);//1 2 2 5
				if(sum==x){
					n[num].i=i;
					n[num++].j=j;
				}
			}
		}
	}
	if(num==0) puts("0");
	else {
		printf("%d\n",num);
		for(i=0;i<num;i++){
			printf("%d ",n[i].j-n[i].i+1);
			printf("%d",n[i].i);
			for(j=n[i].i+1;j<=n[i].j;j++) printf(" %d",j);
			puts("");
		}
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值