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 }