[hdu4710 Balls Rearrangement]分段统计

题意:求∑|i%a-i%b|,0≤i<n

思路:复杂度分析比较重要,不细想还真不知道这样一段段跳还真的挺快的=.=

  • 令p=lcm(a,b),那么p就是|i%a-i%b|的循环节。考虑计算n的答案,令答案为f(n),则最后的结果可以表示为n/p*f(p)+f(n%p)
  • 考虑计算f(n),设两个指针i、j,表示当前累加答案的起始位置分别对a和b取模的结果,则每次i与j中间的一个可以变成0,跳过的一段区间中答案是相同的。
  • 复杂度分析,令a<b,则每次跳过的区间长度近似等于a,则总的复杂度为O(n/a)=O(lcm(a,b)/a)=O(b),也就是说复杂度大致为O(max(a,b))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#pragma comment(linker, "/STACK:10240000")
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define X                   first
#define Y                   second
#define pb                  push_back
#define mp                  make_pair
#define all(a)              (a).begin(), (a).end()
#define fillchar(a, x)      memset(a, x, sizeof(a))
#define copy(a, b)          memcpy(a, b, sizeof(a))

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

#ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}

const double PI = acos(-1.0);
const int INF = 1e9 + 7;
const double EPS = 1e-12;

/* -------------------------------------------------------------------------------- */

ll a, b, n;

ll gcd(ll a, ll b) {
    return b? gcd(b, a % b) : a;
}

ll lcm(ll a, ll b) {
    return a * b / gcd(a, b);
}

ll solve(ll n) {
    ll p = 0, q = 0, c = 0, ans = 0;
    while (c < n) {
        ll buf = min(a - p, b - q);
        umin(buf, n - c);
        c += buf;
        ans += buf * abs(p - q);
        p = (p + buf) % a;
        q = (q + buf) % b;
    }
    return ans;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    int T;
    cin >> T;
    while (T --) {
        cin >> n >> a >> b;
        ll p = lcm(a, b);
        cout << (p <= n? n / p * solve(p) : 0) + solve(n % p) << endl;
    }
    return 0;
}
时间: 2024-10-10 13:14:15

[hdu4710 Balls Rearrangement]分段统计的相关文章

MySQL分段统计SQL写法 与 Mybatis 报错:java.math.BigDecimal cannot be cast to java.lang.Integer

mysql> select -> sum(case when score<60 then 1 else 0 end) as '<60', -> sum(case when score>=60 and score<=69 then 1 else 0 end) as '60~69', -> sum(case when score>=70 and score<=79 then 1 else 0 end) as '70~79', -> sum(ca

hduoj 4710 Balls Rearrangement 2013 ACM/ICPC Asia Regional Online —— Warmup

http://acm.hdu.edu.cn/showproblem.php?pid=4710 Balls Rearrangement Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 735    Accepted Submission(s): 305 Problem Description Bob has N balls and A b

hdu 4710 Balls Rearrangement (数学思维)

题意:就是  把编号从0-n的小球对应放进i%a编号的盒子里,然后又买了新盒子, 现在总共有b个盒子,Bob想把球装进i%b编号的盒子里.求重置的最小花费. 每次移动的花费为y - x ,即移动前后盒子编号的差值的绝对值. 算法: 题目就是要求                  先判断  n与  lcm(a,b)的大小,每一个周期存在循环,这样把区间缩短避免重复计算. 如果n>lcm(a,b)则   ans = (n/lcm)*solve(lcm)+solve(n%lcm) 否则   ans =

hdu 4611 Balls Rearrangement 数学

Balls Rearrangement Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Problem Description Bob has N balls and A boxes. He numbers the balls from 0 to N-1, and numbers the boxes from 0 to A-1. To find the balls easily

mysql 分段统计数据

一个简单的分段统计的问题:student 表{id,name,score} 字段,统计各个分数段的人数.规则:60以下不及格,60-80良,80-100优. SELECT sum(CASE when score<60 then 1 else 0 end) AS '不及格',sum(CASE when score>=60 and score<=80 then 1 else 0 end) AS '良',sum(CASE when score>80 then 1 else 0 end)

MYSQL分段统计

产品表 CREATE TABLE `product` ( `product_id` int(11) NOT NULL AUTO_INCREMENT, `product_model` varchar(255) NOT NULL, `product_price` decimal(15,4) NOT NULL, `product_status` tinyint(1) unsigned NOT NULL, `product_add_time` int(11) unsigned DEFAULT '0',

用sql语句实现年龄分段统计

SELECT CASE WHEN (age >= 10 AND age <= 20) THEN '10-20' WHEN (age >= 21 AND age <= 30) THEN '21-30' ELSE '30-' END 'eag_layer', count(*) emps FROM address_book GROUP BY CASE WHEN (age >= 10 AND age <= 20) THEN '10-20' WHEN (age >= 21

【瞎搞】 HDU 4710 Balls Rearrangement

题目地址:点击打开链接 题意:有N 个小球,编号 0--N-1 两个序列      第 i 个 球 Xi = (i mod A ) 第i个 Yi=(i mod B ) 求   sigma(|Xi-Yi |) 可以知道总有一段 Xi 与Yi 的差是相等的 模拟下可以加快速度. #include <cstdio> #include <cstring> #include <cstdlib> #include <string> #include <iostre

HDU 4611

Balls Rearrangement Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 2862    Accepted Submission(s): 1071 Problem Description Bob has N balls and A boxes. He numbers the balls from 0 to N-1, and