题目链接点这儿
首先。。。肯定是试直接模拟。。。不意外TLE。。。
然后,可以发现它是由循环节的,那就是当lcm(a,b)<n时,有循环节。兴冲冲的写了一个交,然后仍然TLE。。。想起来当n很大但是lcm更大的情况还是没有优化。。。当时都要心灰意冷了。。。
纸上模拟了一个n=13,a=3,b=5的情况。。。
发现了一个东西。。。
球上标的数字 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
初始位置 | 0 | 1 | 2 | 0 | 1 | 2 | 0 | 1 | 2 | 0 | 1 | 2 | 0 | 1 |
新位置 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 2 | 3 |
差值绝对值 | 0 | 0 | 0 | 3 | 3 | 2 | 1 | 1 | 1 | 4 | 1 | 1 | 2 | 2 |
然后就有了下面的代码
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <climits> #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)>(b)?(b):(a)) #define rep(i,initial_n,end_n) for(ll (i)=(initial_n);(i)<(end_n);i++) #define repp(i,initial_n,end_n) for(ll (i)=(initial_n);(i)<=(end_n);(i)++) #define reep(i,initial_n,end_n) for((i)=(initial_n);(i)<(end_n);i++) #define reepp(i,initial_n,end_n) for((i)=(initial_n);(i)<=(end_n);(i)++) #define eps 1.0e-9 #define MAX_N 1010 using namespace std; typedef pair<int, int> pii; typedef pair<double, double> pdd; typedef __int64 ll; typedef unsigned __int64 ull; ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); } ll val_loop(ll n, ll a, ll b); int main() { ll nn; scanf("%I64d", &nn); while(nn--) { ll n, a, b; scanf("%I64d%I64d%I64d", &n, &a, &b); if(a < b) swap(a,b); ll g = gcd(a,b); ll lcm = (ll)(a*b/g); ll quo = n / lcm, mod = n % lcm; if(a == b) { puts("0"); continue; } if(n <= lcm) printf("%I64d\n", val_loop(n, a, b)); else printf("%I64d\n", quo * val_loop(lcm, a, b) + val_loop(mod, a, b)); //printf("1 = %lld 2 = %lld\n", quo * val_loop(lcm, a, b) , val_loop(mod, a, b)); } return 0; } ll val_loop(ll n, ll a, ll b) { ll i = 0, ta = 0, tb = 0; ll ans = 0, p = 0; while(i < n) { //printf("ta %d tb %d i %d p %lld\n", ta, tb, i, p); // printf("ta + a = %d tb + b = %d\n", ta + a, tb + b); if(ta + a >= n && tb + b >= n) { ans += p * (n-i); i = n; break; } else if(ta + a < tb + b) { ans += p * (ta + a - i); ta += a; i = ta; p = i - tb; } else if(ta + a > ta + b) { ans += p * (tb + b - i); tb += b; i = tb; p = i - ta; } else { ans += p * (ta + a - i); i = ta; ta += a, tb += b; p = 0; } } return ans; }