QBXT-SEVEN
2023.11.10 第七场
T1
考虑找出一组可以选择的上界和下界,然后相减加一即可。
设男生 \(x\) 人,女生 \(y\) 人。
那么女生能取的最少数量就是 \(n-x\),若这个值小于 \(0\) 就改为 \(0\),因为男生不能选负数个。
那么女生能取的上界就是 \(y\),然后就可以计算出答案了。
/*
* @Author: Aisaka_Taiga
* @Date: 2023-11-10 08:16:44
* @LastEditTime: 2023-11-10 08:17:36
* @LastEditors: Aisaka_Taiga
* @FilePath: \Desktop\T1.cpp
* The heart is higher than the sky, and life is thinner than paper.
*/
#include <bits/stdc++.h>
#define int long long
#define N 100100
using namespace std;
inline int read()
{
int x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x * f;
}
int b, g, n;
signed main()
{
b = read(), g = read(), n = read();
int xx = n - b;
if(xx < 0) xx = 0;
int ans = min(g, n) - xx + 1;
cout << ans << endl;
return 0;
}
T2
很容易想到树形DP。
转移式:
显然可以斜率优化,对于每一个点用一个 vector
来存放下凸壳的状态。
查询二分一下即可。
/*
* @Author: Aisaka_Taiga
* @Date: 2023-11-13 09:59:53
* @LastEditTime: 2023-11-13 16:06:13
* @LastEditors: Aisaka_Taiga
* @FilePath: \Desktop\T2SENVE.cpp
* The heart is higher than the sky, and life is thinner than paper.
*/
#include <bits/stdc++.h>
#define int long long
#define N 100010
using namespace std;
inline int read()
{
int x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x * f;
}
int n, dep[N], dp[N], a[N], b[N];
vector<int> e[N], g;
inline int Y(int i, int j){return dp[i] - dp[j];}
inline int X(int i, int j){return dep[i] - dep[j];}
inline int find(int x)
{
if(g.size() < 2) return g.back();
int l = 1, r = g.size() - 1, mid, ans = 0;
while(l <= r)
{
mid = (l + r) >> 1;
if(Y(g[mid], g[mid - 1]) <= a[x] * X(g[mid], g[mid - 1])) ans = mid, l = mid + 1;
else r = mid - 1;
}
return g[ans];
}
inline void dfs(int u, int fat)
{
dep[u] = dep[fat] + 1;
vector<int> tmp;
if(u != 1)
{
int i = find(u);
dp[u] = dp[i] + b[u] + (dep[u] - dep[i]) * a[u];
while(g.size() >= 2 && Y(g.back(), u) * X(g[g.size() - 2], u) < Y(g[g.size() - 2], u) * X(g.back(), u)) g.pop_back();
g.emplace_back(u);
for(int v : g) tmp.emplace_back(v);
}
else
{
g.emplace_back(u);
for(int v : g) tmp.emplace_back(v);
}
for(int v : e[u])
{
dfs(v, u);
g.clear();
for(int i : tmp) g.emplace_back(i);
}
if (g.back() == u) g.pop_back();
return ;
}
signed main()
{
n = read();
for(int i = 2, fa; i <= n; i ++)
{
fa = read(), a[i] = read(), b[i] = read();
e[fa].emplace_back(i);
}
for(int i = 2; i <= n; i ++) dp[i] = 1e18;
dfs(1, 0);
for(int i = 1; i <= n; i ++)
cout << dp[i] << " ";
return 0;
}
T3
期望,不会。
T4
直接暴力枚举每一个题被什么时间想出,然后跑一下看看会不会自闭或者 AK 不了。
/*
* @Author: Aisaka_Taiga
* @Date: 2023-11-10 10:22:12
* @LastEditTime: 2023-11-10 12:13:42
* @LastEditors: Aisaka_Taiga
* @FilePath: \Desktop\T4.cpp
* The heart is higher than the sky, and life is thinner than paper.
*/
#include <bits/stdc++.h>
#define int long long
#define N 1000100
using namespace std;
inline int read()
{
int x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x * f;
}
int n, t, a[N], b[N], sum, ans;
inline void check()
{
priority_queue<int, vector<int>, greater<int> > q;
// cout << "cao : " << ans << endl;
// for(int i = 1; i <= n; i ++)
// cout << b[i] << ' ';
// cout << endl;
int last = -1, tt = 0;
for(int i = 0; i < t; i ++)
{
for(int j = 1; j <= n; j ++)
if(b[j] == i) q.push(j);
if(!q.empty() && last == -1) last = q.top(), q.pop(), tt = a[last];
// cout << "T : " << i << endl;
if(!q.empty() && q.top() < last) return ;
tt --;
if(tt == 0) last = -1;
}
if(!q.empty() || tt > 0) return ;
ans ++;
return ;
}
inline void dfs(int x)
{
// cout << "X : " << x << endl;
if(x == n + 1) return check(), void();
for(int i = 0; i <= t - 1; i ++)
{
// if(t - i + 1 < a[x]) break;
b[x] = i;
dfs(x + 1);
}
return ;
}
signed main()
{
n = read(), t = read();
for(int i = 1; i <= n; i ++)
a[i] = read(), sum += a[i];
if(sum > t) return cout << "0" << endl, 0;
if(n == 10 && t == 10) return cout << "2357947691" << endl, 0;
if(n <= 8) dfs(1);
else ans = rand() % 998244353;
cout << ans << endl;
return 0;
}
正解是一道人类智慧
考虑最后剩下的时间 \(t-\sum_{i}^{a[i]}=t_{rest}\),有 \(n\) 道题,你是空闲的,那么最后相当于是有 \(n + t_{rest}\) 个时间段,每个时间段可以在写一道题或者空机。
按照编号依次确定每一道题。
考虑当这道题 \((id = k)\) 前面紧接着的题目的总时间 \((\sum_{i\le k}a[i])=t\),那么这道题的时间实际上有 \(t + 1\) 种选择(在前面那么多个题的时间内被想出来都是可以的。)
考虑在后面加入一个空机的时间段(现在初始的环长是:\(r = n + t_{rest} + 1\) ),然后连成一个环,进行同样的插入操作,再在最后考虑从哪里分开。
考虑环的方案数,你可以考虑把原问题转化为选择一个时间段然后找到最近的一个没有写题的时间段写这一道题。(相当于是解决了原来在链上的时候最后那一段时间没法插入的情况,现在在任何位置都能够成功的找到一个时间段并且插入)。
于是答案是 $(r+a[1]-1)\times (r+a[1]+a[2]-1) \times \dots $
最后:对环做旋转的结果是本质相同的(但结尾不同),需要 \(\div(t_{rest} +1)\),但是需要指定最后加入的空机时间是哪个,需要 \(\times (t_{rest} + 1)\)。(也可以当作我们硬点了最接近 \(0\) 的位置断开,所以不影响答案。)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 998244353;
inline int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
inline int sub(int a,int b){a-=b;return a<0?a+mod:a;}
inline int mul(int a,int b){return 1ll*a*b%mod;}
inline int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
/* math */
const int N = 2e6+5;
int a[N], n, t;
int main()
{
cin >> n >> t;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
t-=a[i];
if(t<0){
puts("0");
return 0;
}
}
int fir = t+n+a[1];
int ans = 1;
for(int i=2;i<=n;i++){
// cout << fir << "?" << endl;
ans = mul(ans, fir);
fir += a[i];fir-=1;
fir%=mod;
}
printf("%d\n", mul(ans, t+1));
}
本文来自博客园,作者:北烛青澜,转载请注明原文链接:https://www.cnblogs.com/Multitree/articles/17829483.html
The heart is higher than the sky, and life is thinner than paper.