切水题也越来越慢,2700就开始无力,我是不是已经废掉了。
CF1671A String Building
单 a
和单 b
不能解决,其余都可。
CF1671B Consecutive Points Segment
注意到结局只有三种起始数值,一种是最小值,一种是最小值减 1,一种是最小值加 1。
枚举结束态的开头,然后判断一下可否。
CF1671C Dolce Vita
显然每天会从小到大依次购买。
对每个物品二分一下最多会有几天能够买到他。
CF1671D Insert a Progression
注意到插入一个数不会使答案变大当且仅当,插入的位置的两端的数一个比插入的数字大,一端小。
那么考虑原始数列的最大最小值 mx
和 mi
。
那么插入 \([mi , mx]\) 之间的数答案不会变大。
现在考虑插入剩下的大于 mx
的数和小于 mi
的数。显然他们连续插入。
发现插入到中间贡献一定,都是二倍极差。插入到两头贡献比较特殊。
讨论一下即可。
int main() {
int T;
read(T);
while(T -- > 0) {
read(n),read(x);
int Mx = 0 , Mi = 1e9;
LL ans = 0;
for (int i = 1; i <= n; ++i) read(a[i]) , Mx = max(Mx , a[i]) , Mi = min(Mi , a[i]);
for (int i = 1; i < n; ++i) ans += Abs(a[i] - a[i + 1]);
if(Mi > 1) {
int c = min(Mi - 1 , x);
ans += min((Mi - 1) * 2 , min(a[1] , a[n]) - 1);
}
if(Mx < x) {
ans += min((x - Mx) * 2 , x - max(a[1] , a[n]));
}
write(ans);
}
return 0;
}
CF1671E Preorder
考虑一个点及其子树。
若其左右子树不等价,则它们没有任何一种组合方案相同,则 \(f_x = 2 \times f_{ls} \times f_{rs}\)。
否则就只是 \(f_x = f_{ls} \times f_{rs}\)。
现在只需要判断是否等价,那么我们只需要把先序遍历通过交换左右子树将其形成字典序最小,比较字符串即可知。
类比归并排序或者说 dsu
啥的,随便做一下就好了。
CF1671F Permutation Counting
注意到 \(n\) 很大,\(k,x\) 很小,那么就可以感受到大量的 \(a_{i} = i\)。
那么不妨将 \(a\) 划分一下,使每段之间互不影响逆序对数和下降对数,具体地我们把 \(mx_{i} = i\) 的位置剖开。
同时我们剔去长度为 \(1\) 的段,那么注意到每段一定对下降对和逆序对有正贡献,那么段数不超过 \(11\)。
同时每段长度一定不超过 \(12\) (简单构造可知)。
于此同时,有用段的总长度不会超过 \(22\)。
因此我们把所有有用段搜出来(不会很多)。
然后把他们视作物品背包处理一下,记录选了多少个数,多少段,多少逆序对和下降对。
最后再乘上一些组合数就好了。
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <iostream>
#include <algorithm>
#define pii pair <int , int>
#define pll pair <LL , LL>
#define mp make_pair
#define fs first
#define sc second
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
//const int Mxdt=100000;
//static char buf[Mxdt],*p1=buf,*p2=buf;
//#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,Mxdt,stdin),p1==p2)?EOF:*p1++;
template <typename T>
void read(T &x) {
T f=1;x=0;char s=getchar();
while(s<'0'||s>'9') {if(s=='-') f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=(x<<3)+(x<<1)+(s-'0');s=getchar();}
x *= f;
}
template <typename T>
void write(T x , char s='\n') {
if(!x) {putchar('0');putchar(s);return;}
if(x<0) {putchar('-');x=-x;}
T tmp[25]={},t=0;
while(x) tmp[t++]=x%10,x/=10;
while(t-->0) putchar(tmp[t]+'0');
putchar(s);
}
const int mod = 998244353;
inline int Add(int x , int y) {x += y;return x >= mod?x - mod:x;}
inline int Sub(int x , int y) {x -= y;return x < 0?x + mod:x;}
inline int Mul(int x , int y) {return 1ll * x * y % mod;}
inline int qpow(int a , int b) {
int res = 1;
while(b) {
if(b & 1) res = Mul(res , a);
a = Mul(a , a);
b >>= 1;
}
return res;
}
int v[15][15][15] , vis[15] , d[15];
void dfs(int x , int mx , int inv , int dw) {
if(inv > 11 || dw > 11) return;
if(x - 1 == mx) {
v[x - 1][inv][dw] ++;
return;
}
int now = 0;
for (int i = 1; i <= 12; ++i) if(!vis[i]) {
d[x] = i , vis[i] = 1;
dfs(x + 1 , max(mx , i) , inv + now , dw + (d[x - 1] > i));
vis[i] = 0;
now ++;
}
}
int f[25][15][15][15] , Inv[15];
int main() {
dfs(1 , -1 , 0 , 0);
f[0][0][0][0] = 1;
for (int t = 2; t <= 22; ++t) {
for (int d = 1; d <= 11; ++d) {
for (int p = 1; p <= 11; ++p) {
for (int q = 1; q <= 11; ++q) {
for (int i = 2; i <= min(12 , t); ++i) {
for (int j = 1; j <= p; ++j) {
for (int k = 1; k <= q; ++k) if(v[i][j][k]) {
f[t][d][p][q] = Add(f[t][d][p][q] , Mul(f[t - i][d - 1][p - j][q - k] , v[i][j][k]));
}
}
}
}
}
}
}
for (int i = 1; i <= 11; ++i) Inv[i] = qpow(i , mod - 2);
int T;
read(T);
while(T -- > 0) {
int n , k , x;
read(n),read(k),read(x);
int ans = 0;
for (int i = 1; i <= min(22 , n); ++i) {
int now = n - i + 1;
for (int j = 1; j <= 11; ++j) {
ans = Add(ans , Mul(f[i][j][k][x] , now));
now = Mul(now , Mul(n - i + j + 1 , Inv[j + 1]));
}
}
write(ans);
}
return 0;
}