Educational Codeforces Round 88 (Rated for Div. 2)(C~E)

比赛连接

C. Mixing Water

题目描述

向一个无穷深的容器轮流倒入温度为 h 的热水和温度为 c 的冷水,至少倒入一次热水,问最接近 t 度时需要倒几杯水。

思路

只要倒入杯数为偶数的情况时,杯中温度都是 h+c2\frac{h+c}{2},倒入杯数是奇数的情况时,杯中温度都是 (设倒入2n - 1杯) nh+(n1)c2n1\frac{n*h + (n-1) * c}{2n - 1} 。所以最低温度情况是 h+c2\frac{h+c}{2},将奇数杯的情况化简不等式:
nh+(n1)c2n1nh+(n1)h2n1\frac{n*h + (n - 1) * c}{2n - 1}\leq\frac{n * h + (n - 1) * h}{2n - 1} = h
所以最高温是h度,当 t >= h 时特判返回1, t <= h+c2\frac{h+c}{2} 时特判返回 2 。那么其余的状况就都是奇数的数量。
根据上面的思路分析可得res=2n1res=2*n-1,那么根据公式 nh+(n1)c2n1=t\frac{n*h + (n - 1) * c}{2n - 1}=t 可以化简得出 n=cth+c2tn=\frac{c-t}{h+c-2t},那么答案 res=2(ct)h+c2t1res=\frac{2(c-t)}{h+c-2t}-1. 因为这个res求出来是整数,但是可能实际上存在一些精度误差,就要向两边的奇数都去验证一遍寻找最小值

代码

double h, c, t;

double cacl(int x) {
   return ((x + 1) / 2 * h + x / 2 * c) / x;
}

void solve() {
   cin >> h >> c >> t;
   double mid = (h + c) / 2;
   if(t <= mid) {
   	puts("2");
   	return;
   }
   if(t >= h) {
   	puts("1");
   	return;
   }
   int l = 1, r = mod;
   int res = 2 * (c - t) / (h + c - 2 * t) - 1;
   if(!(res & 1)) res ++;
   double tmp = cacl(res);
   for(int i = max(res - 2, 1); i <= res + 2; i++) {
   	if(i & 1) {
   		if(fabs(cacl(i) - t) < tmp) {
   			tmp = fabs(cacl(i) - t);
   			res = i;
   		}
   	}
   }
   printf("%d\n", res);
}

D.Yet Another Yet Another Task

题目描述

在给定数组中寻找一个区间 [l, r] (ll\leqr) 且减去该区间中最大值的最大值

思路

数据范围 30a[i]30-30\leq a[i] \leq 30,如果是负数的区间最大值那一定只选一个负数并删除它,最大值为0,所以只要枚举最大值为1~30的所有情况。

代码

const int N = 1e5 + 10;
int a[N];

void solve() {
   int n;
   scanf("%d", &n);
   for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
   int res = 0;
   for(int i = 1; i <= 30; i++) {
   	int sum = 0;
   	for(int j = 1; j <= n; j++) {
   		if(a[j] > i) sum = 0; // 当前存在的数大于所枚举的最大数,当作不存在
   		else {
   			sum += a[j];
   			if(sum < 0) sum = 0;
   			else res = max(res, sum - i);	// sum - i减去区间最大值
   		}
   	}
   }
   printf("%d\n", res);
}

E. Modular Stability

题目描述

给定一个n,k。求有多少组序列{a1, a2, … , ak} 满足 1 \leq a1 < a2 < … < ak \leq n 且对于任意的数 x 满足按任意顺序取模都相等的结果。

思路

对于任意的数,都要满足 an(n > 1) 为a1的倍数,因为当 an 取模不管取到多少时,满足 x mod an \geq x mod a1,若 x mod an > x mod a1, 那么 a1 一定可以再对 x mod an 取模 。这个结论是比较显然的。最后用一下逆元组合数取模的方式就行了

代码

LL f[N], inv[N];

LL kpow(LL a, LL n) {
   LL res = 1;
   while(n) {
   	if(n & 1) res = (res * a) % mod;
   	a = (a * a) % mod;
   	n >>= 1;
   }
   return res;
}

void init() {
   f[0] = inv[0] = 1;
   for(int i = 1; i < N; i++) {
   	f[i] = (f[i - 1] * i) % mod;
   	inv[i] = (inv[i - 1] * kpow(i, mod - 2)) % mod;
   }
}

void solve() {
   init();
   int n, k;
   scanf("%d%d", &n, &k);
   if(n < k) {
   	puts("0");
   	return;
   }
   LL res = 0;
   for(int i = 1; i <= n / k; i++) {
   	LL cnt = n / i;
   	res = (res + f[cnt - 1] * inv[k - 1] % mod * inv[cnt - k] % mod) % mod;
   }
   printf("%lld\n", res);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章