【LGR-268-Div.2】洛谷 2 月月赛 IV & TBOI Round 1
P15409 「TBOI Round 1」Niton & LCM
只考虑 \(k\) 的因数,发现这些数的最小公倍数是 \(k\) 的因数,所以直接将所有 \(k\) 的因数求最小公倍数即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int kN = 1e5 + 7;
int n, k, a[kN];
int gcd(int a, int b){
if(!b) return a;
return gcd(b, a % b);
}
void solve(){
cin >> n >> k;
for(int i = 1; i <= n; i++) cin >> a[i];
int f1 = 1, f2 = 0;
for(int i = 1; i <= n; i++){
if(k % a[i] == 0){
f1 = f1 / gcd(f1, a[i]) * a[i];
f2 = 1;
}
}
if(f1 == k && f2) cout << "Yes\n";
else cout << "No\n";
}
signed main(){
int T = 1; cin >> T;
while(T--) solve();
return 0;
}
P15410 「TBOI Round 1」Niton & Matrix
遇到这种题,我们可以从改变一个点要进行哪些操作,会影响到哪些点入手。比如说这个题,改变一个点的权值会使其关于中轴线对称的点改变。所以整个矩阵会形成若干个四元环,在不改变四元环整体异或和的情况下,可以将一个点的值修改成任意值。
#include <bits/stdc++.h>
using namespace std;
vector< vector<int> > a, b;
int n, m;
void solve(){
cin >> n >> m;
a.resize(n + 3), b.resize(n + 3);
for(int i = 1; i <= n; i++){
a[i].resize(m + 3), b[i].resize(m + 3);
for(int j = 1; j <= m; j++) cin >> a[i][j];
}
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) cin >> b[i][j];
bool fg = 1;
for(int i = 1; i <= n / 2; i++){
for(int j = 1; j <= m / 2; j++){
int A = a[i][j] ^ a[i][m + 1 - j] ^ a[n - i + 1][j] ^ a[n - i + 1][m + 1 - j];
int B = b[i][j] ^ b[i][m + 1 - j] ^ b[n - i + 1][j] ^ b[n - i + 1][m + 1 - j];
if(A != B){fg = 0; break;}
}
}
if(fg) cout << "Yes\n";
else cout << "No\n";
a.clear(), b.clear();
a.shrink_to_fit(), b.shrink_to_fit();
}
signed main(){
int T = 1; cin >> T;
while(T--) solve();
return 0;
}
P15411 「TBOI Round 1」Niton & Killaura
换根 \(dp\) 大杂烩。容易发现最优情况为让颜色相同的点尽量处于同一棵子树中。设状态 \(f_i\) 表示树的根节点为 \(1\) 时,以 \(i\) 为根的子树内最优答案,易得转移:\(f_i=n-\left \lfloor \frac {siz_i}{3} \right \rfloor +\sum_{v\in{son_i}}f_v\),换根易做。
接着看如何计数,设状态 \(dp_i\) 表示树的根节点为 \(1\) 时,以 \(i\) 为根的子树内划分数量,\(dp_i=F_{1+\sum_{v\in son_i}(siz_v\mod 3)}\times \prod_{v\in{son_i}}dp_v\),其中 \(F_i\) 表示将 \(i\) 个元素分成 \(\left \lceil \frac {i}{3} \right \rceil\) 组的方案数,换根易做,答案为划分数量 \(\times n!\)。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
const int kN = 3e5 + 7;
const int INV = 499122177;
void Add(int &x, int y){(x += y) >= mod ? x -= mod : 0;}
int add(int x, int y){Add(x, y); return x;}
int n, f[kN * 3], g[kN * 3], siz[kN * 3], col, jc[kN * 3], jcinv[kN * 3], pow6[kN * 3], invpow6[kN * 3];
int F[kN * 3], dp[kN * 3], dp2[kN * 3], S[kN * 3];
vector<int> ve[kN * 3];
int Pow(int a, int b){
int res = 1; a %= mod;
for(; b; b >>= 1){
if(b & 1) res = res * a % mod;
a = a * a % mod;
} return res;
}
int C(int n, int m){
return jc[n] * jcinv[m] % mod * jcinv[n - m] % mod;
}
void DFS(int x, int fa){
siz[x] = 1; dp[x] = 1; int s = 1;
for(int j : ve[x]){
if(j == fa) continue;
DFS(j, x); siz[x] += siz[j]; s += siz[j] % 3;
f[x] += f[j]; dp[x] = dp[x] * dp[j] % mod;
}
dp[x] = dp[x] * F[s] % mod; S[x] = s;
f[x] += 1ll * (col - siz[x] / 3);
}
void DP(int x, int fa){
for(int j : ve[x]){
if(j == fa) continue;
g[j] = g[x] + 1ll * (siz[j] / 3 - (n - siz[j]) / 3);
dp2[j] = Pow(F[S[j]], mod - 2) * dp2[x] % mod * Pow(F[S[x]], mod - 2) % mod * F[S[x] - siz[j] % 3] % mod * F[S[j] + (n - siz[j]) % 3] % mod;
S[j] += (n - siz[j]) % 3;
DP(j, x);
}
}
signed main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n; col = n; n = n * 3;
jcinv[0] = jc[0] = pow6[0] = invpow6[0] = 1;
for(int i = 1; i <= n; i++) jc[i] = jc[i - 1] * i % mod, jcinv[i] = Pow(jc[i], mod - 2), pow6[i] = pow6[i - 1] * 6ll % mod, invpow6[i] = Pow(pow6[i], mod - 2);
F[0] = 1;
for(int i = 1; i <= n; i++) F[i] = C(i, i % 3) * jc[i - i % 3] % mod * invpow6[(i - i % 3) / 3] % mod * jcinv[(i - i % 3) / 3] % mod;
for(int i = 1, u, v; i < n; i++){
cin >> u >> v; ve[u].push_back(v), ve[v].push_back(u);
}
DFS(1, 0);
g[1] = f[1]; dp2[1] = dp[1];
DP(1, 0);
for(int i = 1; i <= n; i++) cout << g[i] << ' ' << jc[col] * dp2[i] % mod << '\n';
return 0;
}

浙公网安备 33010602011771号