倒序开吧, 你们最想看的应该是D题的题解, 我干了两个小时才搞懂
D.Potion Brewing Class
题意分析: 给定
n
n
n 种原料,
n
?
1
n - 1
n?1 个约束条件, 每种原料的比值必须要满足约束关系, 然后求原料含量最小的总和
首先不妨将题意转化一下,
n
,
n
?
1
n, n - 1
n,n?1, 不难想到是树, 知道是树后, 可以将
n
n
n 种原料看作
n
n
n 个点,
n
?
1
n - 1
n?1 个约束条件可以看作
n
?
1
n - 1
n?1 条边, 然后每两个点之间,要满足点权比等于边权, 我们不妨可以画一个图
a
i
:
a
j
=
x
/
y
a_i : a_j = x / y
ai?:aj?=x/y
a
j
=
a
i
?
y
/
x
a_j = a_i * y / x
aj?=ai??y/x
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353, N = 2e5 + 10;
int qmi(int a,int b)
{
int res = 1;
while(b)
{
if(b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
int n,t;
int Inv[200005];
struct node
{
int v, x, y;
};
vector<node>e[N];
int cnt[200005],Maxcnt[200005];
void Add(int x,int flag)
{
for(int i=2;i * i <= x; i ++)
{
while(x % i == 0)
{
cnt[i] += flag;
x/=i;
Maxcnt[i] = max(Maxcnt[i], cnt[i]);
}
}
if(x != 1)
{
cnt[x] += flag;
Maxcnt[x] = max(Maxcnt[x], cnt[x]);
}
}
void dfs1(int u,int fa,int x = 1,int y = 1)
{
Add(y,-1);
Add(x,1);
for(auto &p : e[u])
{
if(p.v == fa) continue;
dfs1(p.v, u, p.x,p.y);
}
Add(x, -1);
Add(y, 1);
}
int Nowval,ans;
void dfs2(int u,int fa,int x = 1,int y = 1)
{
Nowval = Nowval * y % mod * Inv[x] % mod;
ans = (ans + Nowval) % mod;
for(auto &p : e[u])
{
if(p.v == fa) continue;
dfs2(p.v,u,p.x,p.y);
}
Nowval = Nowval * x % mod * Inv[y] % mod;
}
signed main()
{
ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
cin >> t;
while(t--)
{
cin >> n;
for(int i = 1; i <= n; i ++) Inv[i] = qmi(i, mod-2);
for(int i = 1; i <= n; i ++) e[i].clear();
for(int i = 1; i <= n; i ++) cnt[i] = Maxcnt[i] = 0;
for(int i = 1;i <= n - 1; i ++)
{
int u,v,x,y;
cin >> u >> v >> x >> y;
e[u].push_back({v, x, y});
e[v].push_back({u, y, x});
}
dfs1(1, 0);
Nowval = 1;
ans = 0;
for(int i = 1; i <= n; i ++)
Nowval = (Nowval * qmi(i, Maxcnt[i])) % mod;
dfs2(1, 0);
cout << ans << '\n';
}
}
C. Alice and the Cake
题意: 有一块重量为
w
w
w 的蛋糕, 可以切
n
?
1
n - 1
n?1 次, 每次切出来的蛋糕重量为
w
/
2
w / 2
w/2 向下取整,和
w
/
2
w / 2
w/2 向上取整, 给定了一个 一个蛋糕被切了
n
?
1
n - 1
n?1 次后的每一块蛋糕的重量, 判断这种序列是否存在
首先我们可以模拟切的过程, 先计算出蛋糕的总质量, 然后模拟切的过程, 维护两个优先队列, 一个负责模拟切的过程, 一个是保存给定序列的蛋糕的重量, 每切一次后, 将最大重量的相同的蛋糕去掉, 然后切完后判断另一个队列是否为空即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
void solve()
{
priority_queue<int,vector<int>,less<int>>heap, s;
int n, x;
cin >> n;
int sum = 0;
for(int i = 1; i <= n; i ++ ) cin >> x,sum += x, s.push(x);
heap.push(sum);
while(1)
{
if(heap.top() < s.top())
{
cout << "NO\n";
return;
}
while(heap.top() == s.top())
{
heap.pop();
s.pop();
if(heap.empty()) break;
}
if(heap.empty()) break;
int a = heap.top();
heap.pop();
heap.push(a / 2), heap.push((a + 1 ) / 2);
if(a / 2 == 0) break;
}
if(heap.empty()) cout << "YES\n";
else cout << "NO\n";
}
signed main()
{
int t;
cin >> t;
while(t -- ) solve();
}
B. Prefix Removals
题意分析: 大概就是说把后面出现过的字符给它删去吧,大概就这个意思
#include<bits/stdc++.h>
#define int long long
using namespace std;
int cnt[110];
signed main()
{
int t;
cin >> t;
while(t -- )
{
string s;
memset(cnt, 0, sizeof cnt);
cin >> s;
for(int i = 0; i < (int)s.size(); i ++ )
cnt[s[i] - '0']++;
int bg = 0;
for(int i = 0; i < (int)s.size(); i ++ )
if(cnt[s[i] - '0'] > 1) bg = i + 1,cnt[s[i] - '0']--;
else break;
if(bg == (int)s.size()) bg --;
for(int i = bg; i < (int)s.size(); i ++ )
cout << s[i];
cout << '\n';
}
}
A. Maximum Cake Tastiness
题意分析: 就是要求蛋糕的味道的最大值, 其值就是两个相邻蛋糕间的和的最大值, 然后因为可以改变顺序, 所以一定有一种方法可以让最大和次大值相邻, 所以直接输出最大值和次大值之和即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[1100];
signed main()
{
int t;
cin >> t;
while(t -- )
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++ )
cin >> a[i];
sort(a + 1, a + 1 + n);
cout << a[n] + a[n - 1] << '\n';
}
}
|