先算出lcm(a,b),如果lcm>=n,则直接暴力解决;否则分段,求出0-lcm内的+0-n%lcm内的值。
再就是连续相同的一起计算!!
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<iomanip> 5 #include<cmath> 6 #include<cstring> 7 #include<vector> 8 #include<stdlib.h> 9 #define ll __int64 10 using namespace std; 11 ll gcd(ll a,ll b){ 12 ll t; 13 if(a<b) swap(a,b); 14 while(b){ 15 t=a; 16 a=b; 17 b=t%b; 18 } 19 return a; 20 } 21 ll lcm(ll a,ll b){ 22 return a/gcd(a,b)*b; 23 } 24 ll cal(ll n,ll a,ll b){ 25 ll ans=0; 26 ll temp=0;//记录i后面最小还有多少数在同一段 27 ll x=0,y=0,i=0;//x记录i在a中的位置,y记录i在b中的位置,i指示当前位置 28 while (i<n){ 29 temp = min(a-x,b-y); 30 if (i+temp>n) temp=n-i; //如果i+temp>n 则后面最多只有n-i个数了 31 ans += temp*abs(x-y); //记录连续一段的值 32 x = (x+temp)%a; //更新x的位置 33 y = (y+temp)%b; //更新y的位置 34 i += temp; //更新当前位置 35 } 36 return ans; 37 } 38 int main(){ 39 int t; 40 ll n,a,b,c,ans; 41 cin>>t; 42 while (t--){ 43 scanf("%I64d%I64d%I64d",&n,&a,&b); 44 if(a==b){ 45 cout<<0<<endl; 46 continue; 47 } 48 c=lcm(a,b); 49 if (c>=n) ans = cal(n,a,b); 50 else ans = cal(c,a,b)*(n/c)+cal(n%c,a,b); 51 printf("%I64d ",ans); 52 } 53 return 0; 54 }