Description
yaoge是一个追求完美的人,yaoge认为当他的魅力值为是M的倍数时,才是最帅气的。假设yaoge的初始魅力值为0,但他有N件增加魅力值的道具,第i件道具所能增加的魅力值为i(i = 1,2,……,N)。现yaoge需要从中取出两件道具来增加自己的魅力值,但他又懒得计算总共有多少种方法能让自己变得最帅。希望尼萌能够帮助他。
Input
输入数据的第一行包含一个整数T,表示数据组数。
之后有T组数据,每组数据有两个整数N,M
Output
对于每一组数据,输出一个整数表示满足要求的方案数。
第1 ~ 3组
1<=T<=10,1<=N,M<=1000
第4组
1<=T<=10,0<=N/M<=1000,1<=N,M<=10^9
第5组
1<=T<=1000,1<=N,M<=1000
第 6 ~ 10组
1<=T<=100000,1<=N,M<=10^9
Sample Input
4
1 3
2 3
4 3
10 10
1 3
2 3
4 3
10 10
Sample Output
0
1
2
4
这道题是校内蓝桥杯选拔的一道题,当时过了8个数据,当时用的方法如下:
于是,我重新考虑这道题,发现其实就是简单的初中数学。
思路如下:
n个数分成被m余 0~m-1堆
余数就分为 m堆
每种余数的个数是可以知道的!
那么要取两个数使其和成为m的倍数
就是在余数相加为m或者0的堆里取
k=n/m;
L=n%m;
每堆先分配k个
1-L堆是比L+1~m-1堆多1个的奇葩(划掉)
以n=11,m=5为例
余0: 5 10
余1: 1 6 11
余2: 2 7
余3: 3 8
余4: 4 9
这5堆被分为3组
{0},{1,4},{2,3}
以n=13,m=6为例
{0},{1,5},{2,4},{3}
AC的代码如下:
1
2
4
这道题是校内蓝桥杯选拔的一道题,当时过了8个数据,当时用的方法如下:
#include<iostream>
#include<cstdio>
using namespace std;
int main(void)
{
int t,n,i,minstart,k,m,len;
long long ans;
cin>>t;
while(t--)
{
ans=0;
scanf("%d%d",&n,&m);
minstart=1;
k=(n+n-1)/m;
for(i=1;i<=k;i++)
{
if(minstart+n<i*m)
minstart+=i*m-(minstart+n);
len=i*m-minstart-minstart;
if(len%2==0)
{
ans+=len/2;
}
else
{
ans+=len/2+1;
}
}
cout<<ans<<endl;
}
}
这个方法比起简单的暴力还是快了不少(暴力当时过了4个数据),但在校内OJ重现时还是TLE了。
于是,我重新考虑这道题,发现其实就是简单的初中数学。
思路如下:
n个数分成被m余 0~m-1堆
余数就分为 m堆
每种余数的个数是可以知道的!
那么要取两个数使其和成为m的倍数
就是在余数相加为m或者0的堆里取
k=n/m;
L=n%m;
每堆先分配k个
1-L堆是比L+1~m-1堆多1个的奇葩(划掉)
以n=11,m=5为例
余0: 5 10
余1: 1 6 11
余2: 2 7
余3: 3 8
余4: 4 9
这5堆被分为3组
{0},{1,4},{2,3}
以n=13,m=6为例
{0},{1,5},{2,4},{3}
AC的代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
int main(void)
{
long long ans;
int t;
long long n,m,k,L;
cin>>t;
while(t--)
{
scanf("%lld%lld",&n,&m);
k=n/m;
L=n%m;
if(m%2==0)
{
if(L>=m/2)
ans=(m-1-L)*k*(k+1)+(m/2-m+L)*(k+1)*(k+1)+(k+1)*k/2+(k-1)*k/2;
else if(L==0)
ans=k*(k-1)+(m/2-1)*k*k;
else
ans=k*(k-1)+L*(k+1)*k+(m/2-1-L)*k*k;
}
else
{
if(L>=m/2)
ans=(k-1)*k/2+(m-L-1)*k*(k+1)+(m/2-m+L+1)*(k+1)*(k+1);
else if(L==0)
ans=k*(k-1)/2+m/2*k*k;
else
ans=(k-1)*k/2+L*(k+1)*k+(m/2-L)*k*k;
}
printf("%lld\n",ans);
}
return 0;
}