1. 程式人生 > 實用技巧 >10.28 訓練題題解

10.28 訓練題題解

CodeForces 550B Preparing Olympiad

題目大意:給出n個數字,要求在這n個數中選出至少兩個數字,使得它們的和在l,r之間,並且最大的與最小的差值要不小於x。

解題思路:因為題目給出的n=15,直接二進位制暴力列舉所有的狀況即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<iostream>
 7 #include<vector>
 8
#include<set> 9 #include<queue> 10 #define inf 0x3f3f3f3f 11 using namespace std; 12 typedef long long int ll; 13 const int N = 1e5 + 100; 14 ll n, l, r, x; 15 ll arr[N]; 16 int main() { 17 cin >> n >> l >> r >> x; 18 int ans = 0; 19 for (int i = 0;i < n;i++)cin >> arr[i];
20 sort(arr , arr + n);//排序方便後面比較差值是否大於等於x 21 for (int i = 0;i < (1 << n);i++) { 22 vector<int>v; 23 ll sum = 0; 24 for (int j = 0;j <n;j++) { 25 if ((i>>j)&1)v.push_back(arr[j]), sum += arr[j]; 26 } 27 int sz = v.size();
28 if (sz < 2)continue;//如果vector中的元素<2直接忽略 29 if (sum >= l && sum <= r && (v[sz - 1] - v[0] >= x))ans++; 30 } 31 cout << ans << endl; 32 }

CodeForces 535C Tavas and Karafs

題意大意:給你一個首項為A,公差為B的等差數列,再給你一個N代表有N次詢問,每次詢問會有三個值L,T,M代表在經過T次操作之後以L為左端點的等於0的串最長能有多長。

每一次操作是使任意M個不為0的數字的值都減一。

解題思路:若S(l)的值大於t,無法滿足題意,直接輸出 -1;否則的話,如果滿足t*m要>=S(l)至S(r)的和,則滿足題意。那麼根據這個條件對右端點進行二分查詢即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<iostream>
 7 #include<vector>
 8 #include<set>
 9 #include<queue>
10 #define inf 0x3f3f3f3f
11 using namespace std;
12 typedef long long int ll;
13 const int N = 1e5 + 100;
14 ll a, b, n;
15 ll L, t, m;
16 ll f(ll x) {
17     return a + (x - 1) * b;
18 }
19 bool solve(ll mid) {
20     ll n=mid-L+1;
21     return n*f(L)+n*(n-1)*b/2 <=t*m;
22     //Sn=n*a1+(n-1)*n*d/2等差數列求和公式 
23 }
24 int main() {
25     cin >> a >> b >> n;
26     while (n--) {
27         cin >> L >> t >> m;
28         if (f(L) > t) {
29             puts("-1");continue;
30         }
31         //因為右端點的值一定小於等於t,所以a+(r-1)*b<=t ,r<(t-a)/b+1 
32         ll l = 1, r = (t - a) / b + 1, mid;
33         ll ans;
34         while (r >= l) {
35             mid = l + r >> 1;
36             if (solve(mid))l = mid + 1, ans = mid;
37             else r = mid - 1;
38         }
39         cout << ans << endl;
40     }
41 }

HDU5705 CLOCK

題目大意:給出時間 HH:MM:SS 角度a 問下一個H和M的角度為a的時刻。

解題思路:首先知道時針120秒走1度,分針10秒走一度。故120秒分針和時針相差11度,所以相差一度需要120/11秒,考慮到精度可以讓所有的資料乘以11變成整數。時間從120秒開始列舉,直到滿足條件結束, 由於前面乘以了11,結果需要除以11。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<iostream>
 7 #include<vector>
 8 #include<set>
 9 #include<queue>
10 #define inf 0x3f3f3f3f
11 using namespace std;
12 typedef long long int ll;
13 const int N = 1e5 + 100;
14 int main() {
15     int hh, mm, ss, a, cnt = 0;
16     while (scanf("%d:%d:%d", &hh, &mm, &ss) != EOF) {
17         scanf("%d", &a);
18         int t = hh * 3600 + mm * 60 + ss;//計算出當前時刻 單位是秒 
19         t *= 11;a *= 11;
20         int angle = 0, now_angle = 0;
21         int st = 120;
22         while (1) {
23             angle += 11;
24             if (angle > 360 * 11) now_angle = angle % (11 * 360);//超過1圈就取餘
25             else now_angle = angle;
26             if (now_angle > 180 * 11) now_angle = 360 * 11 - now_angle;//分鐘和時針的夾角,大於180,轉換為180以內。 
27             if (now_angle == a && st > t) break;//度數相同且時間大於原來的時間
28             st += 120;
29         }
30         st %= 43200 * 11;
31         int h = st / (3600 * 11);
32         int m = (st - h * (3600 * 11)) / (60 * 11);
33         int s = (st - h * (3600 * 11) - m * (60 * 11)) / 11;
34         if (h == 24) h = 0;
35         printf("Case #%d: %02d:%02d:%02d\n", ++cnt, h, m, s);
36     }
37 }