ACM-ICPC 2018 青岛赛区网络预赛 J. Press the Button(数学)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4056

题意:有一个按钮,时间倒计器和计数器,在时间[0,t]内,某个数如果是a的倍数则按c次按钮,如果是b的倍数则按d次按钮。按钮的规则为:每次按完之后时间倒计器设为v+0.5,如果当时 led 灯是灭的则变亮,否则计数器+1,时间倒计器到0时led 灯变灭。(时间倒计器无时无刻在减小,最小为0)问最后计数器的数值。

题解:如果在按按钮之前led灯为灭的话,则这次按钮对计数器没有贡献,考虑按按钮之前 led 灯灭的总数可得出答案。显示如果v>=a 或者v>=c,则 led 灯只有一开始是灭的;否则考虑a和c的lcm,因为循环节 lcm。lcm范围内a和b的倍数全部筛出来记录一下到这个数灯灭的次数,注意就是0时刻灯一定是灭的但lcm时刻灯有可能是暗的,需要判断下。

 1 #include <bits/stdc++.h>
 2 #include <iomanip>
 3 //#include <unordered_set>
 4 //#include <unordered_map>
 5 using namespace std;
 6 typedef long long ll;
 7 typedef unsigned long long ull;
 8 #define lc (o<<1)
 9 #define rc (o<<1)^1
10 #define mst(a, b) memset(a, b, sizeof(a))
11 #define pb push_back
12 #define mp make_pair
13 #define pii pair<int, int>
14 #define IOS ios::sync_with_stdio(0);cin.tie(0);
15 #define random(a, b) rand()*rand()%(b-a+1)+a
16 #define EARTH_RADIUS  6371004
17 #define lowerbit(a) (a&(-a))
18 #define rad(d) ((d)*PI/180.0)
19 #define sd(a) scanf("%d",&a)
20 const int maxn = 2e6 + 10, maxm = 15000010, inf = 0x3f3f3f3f;
21 const ll mod = 1e9 + 7;
22 const double pi=acos(-1.0);
23 const double eps = 1e-9;
24 
25 map<ll,bool>vis;
26 ll dp[maxn];
27 vector<ll>vec;
28 
29 int main() {
30 #ifdef local
31     freopen("in", "r", stdin);
32 //    freopen("in", "w", stdout);
33 #endif
34     int T;
35     scanf("%d",&T);
36     while(T--) {
37         vis.clear();
38         vec.clear();
39         int a,b,c,d;
40         ll v,t;
41         scanf("%d%d%d%d%lld%lld",&a,&b,&c,&d,&v,&t);
42         ll lcm = 1ll * a * c / __gcd(a,c);
43         ll ans = (t / a + 1) * b + (t / c + 1) * d;
44         if(v >= a || v >= c) {
45             ans--;
46             printf("%lld
",ans);
47             continue;
48         }
49         for(int i = 0; ; i++) {
50             ll num = 1ll * i * a;
51             if(num > lcm) break;
52             vec.push_back(num);
53             vis[num] = true;
54         }
55         for(int i = 0; ; i++) {
56             ll num = 1ll * i * c;
57             if(num > lcm) break;
58             if(!vis[num]) vis[num] = true, vec.push_back(num);
59         }
60         sort(vec.begin(), vec.end());
61         int sz = vec.size();
62         ll pre = 0;
63         dp[0] = 1;
64         for(int i = 1; i < sz; i++) {
65             dp[i] = dp[i - 1];
66             ll now = vec[i];
67             if(now - pre > v) dp[i]++;
68             pre = now;
69         }
70         if(t <= lcm) {
71             int pos = lower_bound(vec.begin(), vec.end(), t) - vec.begin();
72             if(vec[pos] > t) pos--;
73             printf("%lld
",ans - dp[pos]);
74             continue;
75         }
76         if(dp[sz - 1] != dp[sz - 2]) {
77             ans -= dp[sz - 2] * (t / lcm);
78             t %= lcm;
79             int pos = lower_bound(vec.begin(), vec.end(), t) - vec.begin();
80             if(vec[pos] > t) pos--;
81             ans -= dp[pos];
82         } else {
83             ans -= dp[sz - 1];
84             t -= lcm;
85             ans -= ((dp[sz - 1] - 1) * (t / lcm));
86             t %= lcm;
87             int pos = lower_bound(vec.begin(), vec.end(), t) - vec.begin();
88             if(vec[pos] > t) pos--;
89             ans -= (dp[pos] - 1);
90         }
91         printf("%lld
",ans);
92     }
93     return 0;
94 }
原文地址:https://www.cnblogs.com/scaulok/p/9657365.html