jzoj P2129【2017.4.21普及】礼物

来源:互联网 发布:数控车削编程实例 编辑:程序博客网 时间:2024/05/18 00:15

题目大意:
某商店准备了N个礼品盒,分别用整数1~N进行编号。其中,第i个盒子有i颗糖果。有K个小朋友可以从这N个礼品盒中任意选出两个拿走,他们拿走的糖果并不一定要多,但是一定要能够刚好平分给每个人。即拿走的两个盒子中的糖果总数一定要是K的倍数。现在他们想知道一共有多少种方案可供选择。
1<=N<=10^9,1<=K<=10^9
1<=i<=n
最后一行N=K=0结束输入

题解:
这道题就是求任意2个数的和是k的倍数的数有多少个。
规律+乘法原理+分类讨论:
1.对于任意2个数x、y,x是a的倍数,y是b的倍数,这时a+b=k,那么x+y就是k的倍数。因此,我们可以利用乘法原理逐一配对把任意一对a,b(满足a+b=k),给答案累加 a的倍数的数量*b的倍数的数量。
2.被k整除的,特判。
3.k为偶数时,特判。

再分情况讨论:
1、k为奇数 k < n div 2
2、k为奇数 k>=n div 2
3、k为偶数 k < n div 2
4、k为偶数 k>=n div 2

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