HDU 4611 Balls Rearrangement 数学 循环节优化

来源:互联网 发布:editplus怎么运行java 编辑:程序博客网 时间:2024/06/04 19:43

题目链接点这儿

就是给一个n,a,b求这明显是会很蛋疼的式子。。。

首先。。。肯定是试直接模拟。。。不意外TLE。。。

然后,可以发现它是由循环节的,那就是当lcm(a,b)<n时,有循环节。兴冲冲的写了一个交,然后仍然TLE。。。想起来当n很大但是lcm更大的情况还是没有优化。。。当时都要心灰意冷了。。。

纸上模拟了一个n=13,a=3,b=5的情况。。。

发现了一个东西。。。

球上标的数字012345678910111213初始位置1201201201201新位置01234012340123差值绝对值00033211141122发现了一个东西。。。就是值有一个一个的重复小段。。。然后想起来。。。在遇到下一个0之前,两个数列都是公差为1的等差数列,它们同一个项的差值当然是恒定的。。。所以。。。在循环节内还能继续优化。。。

然后就有了下面的代码

#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 1010using 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;}




0 0
原创粉丝点击