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\n",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\n",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\n",ans); 92 } 93 return 0; 94 }