Copyright (C) IOI日本委員会 1996. All rights reserved.


問題7.

 自然数を、できるだけ少ない個数の平方数の和で表したい。下記のプログラムは、 自然数を入力すると、求める平方数を小さい順に出力する。空欄に2行程度の文を 入れて、プログラムを完成させよ。[2点]

(例)

  入力   出力
     2       1 1
     9       9
    14       1 4 9



QuickBASICプログラム(7)

DEFINT A-Z
CONST MaxInput = 1000, false = 0, true = -1
TYPE Prob7
    NoTerm AS INTEGER    '最小の和の項数
    first AS INTEGER     '和に表したときの最初の平方数
    isSquare AS INTEGER  '平方数か否か
END TYPE
OPTION BASE 1
DIM a(MaxInput) AS Prob7

    PRINT "自然数を入力してください。": INPUT n

    FOR i = 1 TO n: a(i).isSquare = false: NEXT i
    FOR i = 1 TO n
        IF n / i >= i THEN a(i * i).isSquare = true
        IF a(i).isSquare THEN
            a(i).NoTerm = 1: a(i).first = i
        ELSE
            a(i).NoTerm = i + 1
            j = 1
            WHILE j * j < i
                IF a(i - j * j).NoTerm < a(i).NoTerm - 1 THEN
                ---------------------------------------------
               |                  (a)                       |
                ----------------------------------------------
                END IF
                j = j + 1
            WEND
        END IF
    NEXT i

    WHILE n > 0
        PRINT a(n).first; " "; : n = n - a(n).first
    WEND
END


Cプログラム(7)

#include <stdio.h>

#define MAXINPUT 1000
typedef enum { false, true } BOOLEAN;

struct {
    int No_term;        /* 最小の和の項数 */
    int first;          /* 和に表したときの最初の平方数 */
    BOOLEAN is_square;  /* 平方数か否か */
} a[MAXINPUT+1];

void main()
{
   int n,i,j; 
  
   printf("自然数を入力して下さい。\n"); scanf("%d", &n);
    
   for (i=1; i<=n; i++) a[i].is_square = false;
   for (i=1; i<=n; i++) {
       if (n/i >= i) a[i*i].is_square = true;
       if (a[i].is_square) {
           a[i].No_term = 1; a[i].first = i;
       }
       else {
           a[i].No_term = i+1;
           for (j=1; j*j<i; j++) {
               if (a[i-j*j].No_term < a[i].No_term-1) {
                   ----------------------------------------
                  |               (a)                    |
                   ----------------------------------------
               }
           }
       }
   }

   for (; n>0; n -= a[n].first) printf("%d ", a[n].first);
}


Pascalプログラム(7)

program problem7;
const MaxInput=1000;
type prob7 = record
                No_term:integer;    {最小の和の項数}
                first:integer;      {和に表したときの最初の平方数}
                is_square:boolean;  {平方数か否か}
             end;
var n,i,j:integer; a:array[1..MaxInput] of prob7;

begin
    writeln('自然数を入力して下さい。'); readln(n);

    for i:=1 to n do a[i].is_square := false;
    for i:=1 to n do begin
        if n div i >= i then a[i*i].is_square := true;
        if a[i].is_square then begin
            a[i].No_term := 1; a[i].first := i;
        end
        else begin
            a[i].No_term := i+1;
            j := 1;
            while j*j<i do begin
                if a[i-j*j].No_term < a[i].No_term-1 then begin
                    ------------------------------------------
                   |                (a)                     |
                    ------------------------------------------
                end;
                j:=j+1
            end
        end
    end;

    while n>0 do begin
        write(a[n].first,' '); n := n-a[n].first
    end
end.


JOI'96へ戻る

JOIホームページへ戻る