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; }