JZOJ 4.22 2129——【2017.4.21普及】礼物

题目描述

圣诞节这天,某商店准备了N个礼品盒,分别用整数1-N进行编号。其中,编号为1的盒子中有一个糖果,编号为2的盒子中有2个糖果,。。。编号为N的盒子中有N个糖果。这天一早,中山幼儿园的K个小朋友一起来到这间商店。作为当天的第一批顾客,这些小朋友可以从这N个礼品盒中选出两个拿走。小朋友们商量了一会儿后决定,他们拿走的糖果并不一定要多,但是一定要能够刚好平分给每个人。即拿走的两个盒子中的糖果总数一定要使K的倍数。现在他们想知道一共有多少种方案可供选择。

输入

每行两个正整数N和K,其中1<=N<=10^9,1<=K<=10^9。一行N=K=0
表示输入结束,这一行不用处理。

输出

对输入中除了N=K=0外的每一行,输出一行,这一行只有一个数,即其相对应的输入所得到的方案数。

样例输入

1 1
3 2
5 2
50 50
0 0

样例输出

0
1
4
24

数据范围限制

20%的数据N<=100;
80%的数据K<=1000;
每个输入文件最多有200行输入数据。


20%:
直接暴力,o(n`2)枚举每一种情况

代码如下:

var  ans,i,j,x,y,l:longint;
     a:array[0..1000000]of longint;
begin
  assign(input,'gift.in');
  assign(output,'gift.out');
  reset(input);
  rewrite(output);
  while not eoln() do
    begin
      ans:=0;
      l:=0;
      fillchar(a,sizeof(a),#0);
      readln(x,y);
      if (x=0)and(y=0) then begin close(input); close(output); halt; end;
      for i:=1 to x-1 do
        for j:=i+1 to x do
          if (i+j)mod y=0 then inc(ans);
      writeln(ans);
    end;
  close(input);
  close(output);
end.

40%:
40分就要推出简易公式,枚举n个数可能可以拼成m的倍数——z。
①当(z>x)and(((x*2)-z) mod 2=0) max:=max+(x-(z-x)) div 2
②当(z>x)and(((x*2)-z) mod 2=1) max:=max+(x-(z-x)) div 2+1
③当(z<=x)and(z mod 2=0) max:=max+z div 2-1
④当(z<=x)and(z mod 2=1) max:=max+z div 2

代码如下:

var   max,x,y,z:int64;
       i:longint;
begin
  assign(input,'gift.in');
  assign(output,'gift.out');
  reset(input);
  rewrite(output);
  while not eoln() do
    begin
      max:=0;
      readln(x,y);
      if (x=0)and(y=0) then begin close(input); close(output); halt; end;
      for i:=1 to x*2 div y do
        begin
          z:=i*y;
          if z>=x*2 then break;
          if z>x then
            if (x*2-z) mod 2=0 then max:=max+(x-(z-x)) div 2
            else max:=max+(x*2-z) div 2+1
          else if z mod 2<>0 then max:=max+z div 2 else max:=max+z div 2-1;
        end;
      writeln(max);
    end;
  close(input);
  close(output);
end.

100%:
如果有x,y,a,b,x%k==a,y%k==b,a+b==k,则(x+y)%k==0。根据这个特性,我们可以列张表,然后利用乘法原理,一一配对。然而,可以直接被k整除的,要特殊判断;k为偶数时也要特判断。
再分情况讨论:
1、k为奇数且n%k没过k一半时
2、k为奇数且n%k过k一半时
3、k为偶数且n%k没过k一半时
4、k为偶数且n%k过k一半时

代码如下:

var  n,m,x,y,z,x1:int64;
begin
  assign(input,'gift.in');
  assign(output,'gift.out');
  reset(input);
  rewrite(output);
  readln(n,m);
  while (n<>0)and(m<>0) do
    begin
      x:=n div m;
      y:=n mod m;
      z:=(m-1) div 2;
      x1:=x*(x-1)div 2+x*x*z;
      if (m mod 2=0) then x1:=x1+x*(x-1)div 2; 
      if y>0 then
        begin
          if (y>=z) then x1:=x1+x*z else x1:=x1+x*y;
          y:=y-z;
          if (y>0)and(m mod 2=0)then
            begin
              x1:=x1-x*(x-1)div 2+x*(x+1) div 2;
              y:=y-1;
            end;
          if (y>0) then x1:=x1+(x+1)*y;
        end;
      writeln(x1);
      readln(n,m);
    end;
  close(input);
  close(output);
end.

posted @ 2017-04-25 21:11  BEYang_Z  阅读(261)  评论(0编辑  收藏  举报