2013年多校联合第二场的A题..开始以为有数学方法...整了好久都整不出..这种题还是果断的打表找规律...
题目实际上要求的是sigma | x%A - x%B |...把每个数的值打出来..发现是一片一片的相同..所以可以利用这一点.直接把答案算出来..但要注意的是..有可能A,B较小..直接模拟会超时..那么处理分为两种情况..当lcm ( A,B )小于10^6...那么就N取摸直接来找...否则..按照一块一块相同的这样从0推到N...
Program:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<stack>
#include<queue>
#include<algorithm>
#define oo 1000000007
#define ll long long
#define MAXN 1000005
using namespace std;
ll gcd(ll a,ll b)
{
int t;
while (b) {t=a,a=b,b=t%b;};
return a;
}
ll a[MAXN];
int main()
{
ll N,A,B,lcm,temp,ans;
int i,T;
scanf("%d",&T);
while (T--)
{
scanf("%I64d%I64d%I64d",&N,&A,&B);
if (A>B) temp=A,A=B,B=temp;
lcm=A*B/gcd(A,B);
N--;
if (lcm<=100000)
{
a[0]=0;
for (i=1;i<=lcm;i++) a[i]=a[i-1]+abs(i%A-i%B);
ans=a[lcm]*(N/lcm)+a[N%lcm];
}else
{
ll x,h,t,p,a,b;
ans=0;
x=0;
a=A,b=B;
while (x<=N)
{
h=abs(x%A-x%B);
if (a-x<b-x)
{
t=min(a,N+1);
ans+=(t-x)*h;
x=a;
a+=A;
}else
{
t=min(b,N+1);
ans+=(t-x)*h;
x=b;
b+=B;
}
}
}
printf("%I64d\n",ans);
}
return 0;
}