SMU Winter 2025 ptlks的周报Week 4 (2.17-2.22)
这周是蓝桥+天梯,粗心大意丢分有点多。
P10580
解法:
分解y/x的质因数次数,计算贡献
思路
赛时想出来了,但是不小心把自动取模板子里快速幂的数据类型搞错了,直接零蛋了。
代码
点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ooo return
#define itn int
#define double long double
#define int long long
#define PII pair<int,int>
#define PIII pair<int,PII>
#define Endl '\n'
#define Ednl '\n'
#define endl '\n'
#define ednl '\n'
using namespace std;
const int N = 1e5 + 10, M = 32, SZ = (N) << 2, mod = 1e9 + 7;
using i64 = long long;
template<class T> constexpr T mypow(T n, i64 k) {
T r = 1;
for (; k; k /= 2, n *= n) {
if (k % 2) {
r *= n;
}
}
return r;
}
template<int MOD> struct Zmod {
int x;
Zmod(signed x = 0) : x(norm(x % MOD)) {}
Zmod(i64 x) : x(norm(x % MOD)) {}
constexpr int norm(int x) const {
if (x < 0) {
x += MOD;
}
if (x >= MOD) {
x -= MOD;
}
return x;
}
constexpr int val() const {
return x;
}
constexpr Zmod operator-() const {
Zmod val = norm(MOD - x);
return val;
}
constexpr Zmod inv() const {
assert(x != 0);
return mypow(*this, MOD - 2);
}
friend constexpr auto &operator>>(istream &in, Zmod &j) {
int v;
in >> v;
j = Zmod(v);
return in;
}
friend constexpr auto &operator<<(ostream &o, const Zmod &j) {
return o << j.val();
}
constexpr Zmod &operator++() {
x = norm(x + 1);
return *this;
}
constexpr Zmod &operator--() {
x = norm(x - 1);
return *this;
}
constexpr Zmod &operator+=(const Zmod &i) {
x = norm(x + i.x);
return *this;
}
constexpr Zmod &operator-=(const Zmod &i) {
x = norm(x - i.x);
return *this;
}
constexpr Zmod &operator*=(const Zmod &i) {
x = i64(x) * i.x % MOD;
return *this;
}
constexpr Zmod &operator/=(const Zmod &i) {
return *this *= i.inv();
}
constexpr Zmod &operator%=(const int &i) {
return x %= i, *this;
}
friend constexpr Zmod operator+(const Zmod i, const Zmod j) {
return Zmod(i) += j;
}
friend constexpr Zmod operator-(const Zmod i, const Zmod j) {
return Zmod(i) -= j;
}
friend constexpr Zmod operator*(const Zmod i, const Zmod j) {
return Zmod(i) *= j;
}
friend constexpr Zmod operator/(const Zmod i, const Zmod j) {
return Zmod(i) /= j;
}
friend constexpr Zmod operator%(const Zmod i, const int j) {
return Zmod(i) %= j;
}
friend constexpr bool operator==(const Zmod i, const Zmod j) {
return i.val() == j.val();
}
friend constexpr bool operator!=(const Zmod i, const Zmod j) {
return i.val() != j.val();
}
friend constexpr bool operator<(const Zmod i, const Zmod j) {
return i.val() < j.val();
}
friend constexpr bool operator>(const Zmod i, const Zmod j) {
return i.val() > j.val();
}
};
constexpr int MOD[] = {998244353, 1000000007};
using Z = Zmod<MOD[0]>;
Z power(int n) {
return mypow(Z(2), n);
}
vector<int>g[N], gg[N];
int d[N];
Z fac[N], inv[N];
int a[N];
void fact(int n) {
fac[0] = 1;
for (int i = 1; i <= n; i++) {
fac[i] = fac[i - 1] * i;
}
inv[n] = fac[n].inv();
for (int i = n - 1; i >= 0; i--) {
inv[i] = inv[i + 1] * (i + 1);
}
}
Z C(int n, int m) {
if (n < m)return 0;
return fac[n] * inv[m] * inv[n - m];
}
int b[N];
void solve() {
int x, y, n;
cin >> x >> y >> n;
if (y % x) {
cout << 0 << endl;
ooo;
}
int m = y / x;
vector<PII> fact;
for (int i = 2; i * i <= m; ++i) {
int s=0;
while (m % i == 0) {
s++;
m /= i;
}
if(s){
fact.push_back({i,s});
}
}
if (m > 1) fact.push_back({m,1});
if (fact.size()==0) {
cout << 1 << endl;
ooo;
}
Z ans = 1;
for (auto [x, y] : fact) {
Z t1 = mypow(Z(y + 1), n);
Z t2 = (2 * mypow(Z(y), n));
Z t3 = mypow(Z(y - 1), n);
Z tal = t1 - t2 + t3;
ans *= tal;
}
cout << ans << endl;
}
int32_t main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T = 1;
cin >> T;
// euler(1e4);
while (T--) {
solve();
}
return 0;
}
P8769
解法:
从第x天开始枚举到第一天,用最小堆维护最小值。
思路
由于天数越往后选择越少,所以可以直接从最后一天往后枚举,然后再根据天数加入更多合法选择,用堆维护即可。
代码
点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ooo return
#define itn int
#define double long double
#define int long long
#define PII pair<int,int>
#define PIII pair<int,PII>
#define Endl '\n'
#define Ednl '\n'
#define endl '\n'
#define ednl '\n'
using namespace std;
const int N = 1e5 + 10, M = 32, SZ = (N) << 2, mod = 1e9 + 7;
vector<int>g[N], gg[N];
int d[N];
int a[N];
int b[N], c[N];
void solve() {
int x, n;
cin >> x >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i] >> b[i] >> c[i];
if(b[i]<1e5)g[b[i]].push_back(i);
else g[100000].push_back(i);
}
priority_queue<PII, vector<PII>, greater<PII>>q;
for (int i = x; i <= 1e5; i++) {
for (auto u : g[i]) {
q.push({a[u], c[u]});
}
}
int s = 0;
for (int i = x; i >= 1; i--) {
if (q.size() == 0) {
cout << -1 << endl;
return;
}
auto [u, y] = q.top();
q.pop();
y--;
s += u;
if (y) {
q.push({u, y});
}
for (auto v : g[i - 1]) {
q.push({a[v], c[v]});
}
}
cout << s << endl;
}
int32_t main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T = 1;
// cin >> T;
// euler(1e4);
while (T--) {
solve();
}
return 0;
}
P8810
解法:
枚举+dp
思路
数据范围很小,很容易想到dp,每个数都可以由前两个数转移过来。然后考虑如何去环,发现直接枚举其中两个数即可。此时复杂度为\(m^2 \cdot nm^3\)。
代码
点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ooo return
#define itn int
#define int long long
#define PII pair<int,int>
#define PIII pair<int,PII>
#define Endl '\n'
#define Ednl '\n'
#define endl '\n'
#define ednl '\n'
using namespace std;
const int N = 1e3 + 10, M = 32, SZ = (N) << 2, mod = 1e9 + 7;
using i64 = long long;
template<class T> constexpr T mypow(T n, i64 k) {
T r = 1;
for (; k; k /= 2, n *= n) {
if (k % 2) {
r *= n;
}
}
return r;
}
template<int MOD> struct Zmod {
int x;
Zmod(signed x = 0) : x(norm(x % MOD)) {}
Zmod(i64 x) : x(norm(x % MOD)) {}
constexpr int norm(int x) const {
if (x < 0) {
x += MOD;
}
if (x >= MOD) {
x -= MOD;
}
return x;
}
constexpr int val() const {
return x;
}
constexpr Zmod operator-() const {
Zmod val = norm(MOD - x);
return val;
}
constexpr Zmod inv() const {
assert(x != 0);
return mypow(*this, MOD - 2);
}
friend constexpr auto &operator>>(istream &in, Zmod &j) {
int v;
in >> v;
j = Zmod(v);
return in;
}
friend constexpr auto &operator<<(ostream &o, const Zmod &j) {
return o << j.val();
}
constexpr Zmod &operator++() {
x = norm(x + 1);
return *this;
}
constexpr Zmod &operator--() {
x = norm(x - 1);
return *this;
}
constexpr Zmod &operator+=(const Zmod &i) {
x = norm(x + i.x);
return *this;
}
constexpr Zmod &operator-=(const Zmod &i) {
x = norm(x - i.x);
return *this;
}
constexpr Zmod &operator*=(const Zmod &i) {
x = i64(x) * i.x % MOD;
return *this;
}
constexpr Zmod &operator/=(const Zmod &i) {
return *this *= i.inv();
}
constexpr Zmod &operator%=(const int &i) {
return x %= i, *this;
}
friend constexpr Zmod operator+(const Zmod i, const Zmod j) {
return Zmod(i) += j;
}
friend constexpr Zmod operator-(const Zmod i, const Zmod j) {
return Zmod(i) -= j;
}
friend constexpr Zmod operator*(const Zmod i, const Zmod j) {
return Zmod(i) *= j;
}
friend constexpr Zmod operator/(const Zmod i, const Zmod j) {
return Zmod(i) /= j;
}
friend constexpr Zmod operator%(const Zmod i, const int j) {
return Zmod(i) %= j;
}
friend constexpr bool operator==(const Zmod i, const Zmod j) {
return i.val() == j.val();
}
friend constexpr bool operator!=(const Zmod i, const Zmod j) {
return i.val() != j.val();
}
friend constexpr bool operator<(const Zmod i, const Zmod j) {
return i.val() < j.val();
}
friend constexpr bool operator>(const Zmod i, const Zmod j) {
return i.val() > j.val();
}
};
constexpr int MOD[] = {998244353, 1000000007};
using Z = Zmod<MOD[1]>;
Z power(int n) {
return mypow(Z(2), n);
}
int max(int a,int b,int c){
return max(a,max(b,c));
}
vector<PII>g[N];
int a[N], b[N], c[N];
Z dp[N][11][11];
void solve() {
int n, m;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> b[i];
}
Z ans = 0;
for (int l = 0; l <= 10; l++) {
for (int r = 0; r <= 10; r++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j <= 10; j++) {
for (int k = 0; k <= 10; k++) {
dp[i][j][k] = 0;
if (i == 0) {
if (j == l && k == r) {
dp[i][j][k] = 1;
}
}
}
}
}
for (int t = 1; t <= n-2; t++) {
for (int i = 0; i <= 10; i++) {
for (int j = 0; j <= 10; j++) {
for (int k = 0; k <= 10; k++) {
if(max(i,j,k)==b[t-1]){
dp[t][j][k]+=dp[t-1][i][j];
}
}
}
}
}
for (int i = 0; i <= 10; i++) {
for (int j = 0; j <= 10; j++) {
if(max(i,j,l)==b[n-2]&&
max(j,l,r)==b[n-1]){
ans+=dp[n-2][i][j];
}
}
}
}
}
cout<<ans<<endl;
}
int32_t main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T = 1;
// cin >> T;
// euler(1e4);
while (T--) {
solve();
}
return 0;
}
P10418
解法:
树形dp
思路
维护当前子树内包含子树顶点的最长的1条边,2条边,3条边。树形dp越来越顺手了,但是赛时忘开longlong了......
代码
点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ooo return
#define itn int
#define int long long
#define PII pair<int,int>
#define PIII pair<int,PII>
#define Endl '\n'
#define Ednl '\n'
#define endl '\n'
#define ednl '\n'
using namespace std;
const int N = 3e5 + 10, M = 32, SZ = (N) << 2,mod=1e9+7;
vector<PII>g[N];
int a[N],b[N];
itn dp[N][4];
void dfs(int x,int fa){
int s1=0,s2=0,s3=0;
int u1=0,u2=0,u3=0;
int mx2=0,mi2=0,mm2=0,ii2=0;
int mx3=0,mi3=0,mm3=0,ii3=0;
for(auto[s,u]:g[x]){
if(u!=fa){
dfs(u,x);
if(!s1){
u1=u;
s1=s;
}else if(!s2){
u2=u;
s2=s;
}else if(!s3){
u3=u;
s3=s;
}
if(s+dp[u][1]>mx2){
mx2=s+dp[u][1];
mi2=u;
}else if(s+dp[u][1]>mm2){
mm2=s+dp[u][1];
ii2=u;
}
if(s+dp[u][2]>mx3){
mx3=s+dp[u][2];
mi3=u;
}else if(s+dp[u][2]>mm3){
mm3=s+dp[u][2];
ii3=u;
}
}
}
dp[x][1]=s1;
dp[x][2]=max(s1+s2,mx2);
dp[x][3]=max(s1+s2+s3,mx3);
if(u1!=mi2){
dp[x][3]=max(s1+mx2,dp[x][3]);
}else{
dp[x][3]=max(s1+mm2,dp[x][3]);
dp[x][3]=max(s2+mx2,dp[x][3]);
}
}
void solve() {
int n,m;
cin>>n;
for(int i=2;i<=n;i++){
int x,y;
cin>>x>>y;
g[x].push_back({y,i});
g[i].push_back({y,x});
}
for(int i=1;i<=n;i++){
sort(g[i].begin(),g[i].end(),greater<>());
}
dfs(1,0);
itn ans=0;
for(int i=1;i<=n;i++){
// cout<<i<<':'<<dp[i][1]<<" "<<dp[i][2]<<" "<<dp[i][3]<<"\n";
ans=max(ans,dp[i][3]);
}
cout<<ans<<endl;
}
int32_t main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T = 1;
// cin >> T;
// euler(1e4);
while (T--) {
solve();
}
return 0;
}

浙公网安备 33010602011771号