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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章