HDU 4611 Balls Rearrangement

来源:互联网 发布:电脑windows许可证过期 编辑:程序博客网 时间:2024/06/04 19:33

这个题感觉真是非常考验代码能力啊!


做了好长时间才做出来。 思路还是可以慢慢想出来的。


最上来 。 这个题明显是个周期题。 那么找周期就很好找了。 肯定两个箱子的最小公倍数。


但是当数非常大的时候。 比如  a b 都是 99999 99998 这种的时候。  最小公倍数很大。 如果在一个周期内 求值  如果每个箱子枚举的话。


那就明显的太慢。 方法就是 一段一段的求。  我们对 11 3 5 这组样例  写出他的过程。 我们就会发现。 很多地方 相邻的几个球 的在 a箱子 和  b箱子的 差值 是相同的。


利用这个特点。我们就可以顺利解决这个问题了。 注意都是用long long


#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>#include <cmath>#include <cstdlib>#include <string>#include <map>#include <vector>#include <set>#include <queue>#include <stack>#include <cctype>using namespace std;typedef long long ll;typedef unsigned long long ull;#define maxn 100+10#define INF 1<<30ll gcd(ll a, ll b){    return b == 0? a:gcd(b,a%b);}ll on(ll a, ll b, ll t){    ll sum = 0;    if(a == b)        return 0;    for(int i = 0; i < t;){        int m = min(a-i%a,b-i%b);        if(i + m >= t+1){            m = t-i;            i = t;        }//        printf("-----------\n");//        printf("%d %d\n",i,m);        sum += m*abs(i%b-i%a);//        printf("%I64d\n",sum);        i += m;    }    return sum;}int main (){    int t;    scanf("%d",&t);    while(t--){        ll n,a,b;        ll le = 0;        ll sum = 0;        scanf("%I64d%I64d%I64d",&n,&a,&b);        ll m = a*b/gcd(a,b);        if(n >= m){            int k = n/m;            sum += k*on(a,b,m);            le = n - k*m;        }        else            le = n;        sum += on(a,b,le);        printf("%I64d\n",sum);    }    return 0;}


0 0
原创粉丝点击