都高一了才第一次打 c f cf cf 好像太菜了点。。。
C
按 d e p − s i z e dep-size dep−size 排序输出即可
D
枚举中间值,双指针往中间值靠
E
太菜了打的时候只会直接
d
p
dp
dp,
O
(
n
m
2
)
O(nm^2)
O(nm2),大概是
d
p
i
,
l
,
r
dp_{i,l,r}
dpi,l,r 表示第
i
i
i 位,匹配了
[
l
,
r
]
[l,r]
[l,r] 的方案数
这个瓶颈在于每次状态可能从
[
l
,
r
]
[l,r]
[l,r] 变成
0
0
0,也就是说之前选的都不算在前缀,现在重新开始匹配
考虑优化这个过程,我们在
T
T
T 后面加上通配符,每次强制匹配,这样每层的状态就是
O
(
n
)
O(n)
O(n)
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
typedef long long ll;
cs int N = 3e3 + 50;
cs int Mod = 998244353;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Add(int &a, int b){ a = add(a,b); }
void Dec(int &a, int b){ a = dec(a,b); }
void Mul(int &a, int b){ a = mul(a,b); }
char S[N], T[N]; int n, m;
int dp[N][N];
int main(){
#ifdef FSYolanda
freopen("1.in","r",stdin);
#endif
scanf("%s%s",S+1,T+1); n=strlen(S+1); m=strlen(T+1);
for(int i=1; i<=m; i++) if(S[1]==T[i]) dp[i][i]=2;
for(int i=m+1; i<=n; i++) dp[i][i]=2;
for(int i=2; i<=n; i++)
for(int l=1; l<=n; l++){
int r=l+i-1; if(r>n) break;
if(r>m||S[i]==T[r]) Add(dp[l][r],dp[l][r-1]);
if(l>m||S[i]==T[l]) Add(dp[l][r],dp[l+1][r]);
} int as = 0;
for(int i=m; i<=n; i++) Add(as,dp[1][i]);
cout << as;
return 0;
}
F
交互题:初始集合是值域 [ 1 , n ] [1,n] [1,n],每个数出现次数 [ 0 , n ] [0,n] [0,n] 的集合,你可以知道当前集合中形如 { i , i , i } , { i − 1 , i , i + 1 } \{i,i,i\},\{i-1,i,i+1\} {i,i,i},{i−1,i,i+1} 的子集个数,每次可以插入一个数,要猜出初始集合,插入次数 ≤ n \le n ≤n
有插
2
n
2n
2n 次直接得到答案的,每 3 个分组可以插
4
/
3
n
4/3n
4/3n 次得到答案
每个插一次可以
O
(
2
n
)
O(2^n)
O(2n) 得到答案,那么我们将上述方法结合一下,就有如下巧妙的构造
考虑插 2 次可以确定 n n n,那么我们先插 n n n,知道 a n − 1 ∗ a n − 2 a_{n-1}*a_{n-2} an−1∗an−2,然后插 n − 1 n-1 n−1,再插 n n n 得到 ( a n − 1 + 1 ) ∗ ( a n − 2 ) (a_{n-1}+1)*(a_{n-2}) (an−1+1)∗(an−2),这样就可以得到 a n − 2 a_{n-2} an−2,进一步得到 a n − 1 a_{n-1} an−1
那么最终的策略可以为:从
2
2
2 插到
n
−
2
n-2
n−2,插
n
n
n,插
n
−
1
n-1
n−1,插
n
n
n,然后顺推到
1
1
1
最巧妙的地方就是将
n
n
n 分到两次加,可以多获得一个信息
#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 105;
typedef long long ll;
ll A, B, dA, dB;
int n; ll a[N], b[N];
void work(int u){
cout<<"+ "<<u<<endl<<endl;
dA=A; dB=B;
scanf("%lld%lld",&A,&B); dA=A-dA; dB=B-dB;
}
int get(ll x){
if(x==0) return 1;
for(int i=2; i<=n+2; i++) if((i*(i-1)>>1)==x) return i;
}
int main(){
#ifdef FSYolanda
freopen("1.in","r",stdin);
#endif
scanf("%d",&n);
scanf("%lld%lld",&A,&B);
memset(a,-1,sizeof(a));
for(int i=2; i<=n-2; i++){
work(i); b[i]=dB;
} work(n); ll dt=dB;
work(n-1); b[n-1]=dB;
work(n); a[n]=get(dA)-1;
a[n-2]=dB-dt-1;
a[n-1]=dt/(a[n-2]+1);
b[n-1]-=(a[n-2]+1)*(a[n]+1);
for(int i=n-3; i>=1; i--){
a[i]=b[i+2]/(a[i+1]+1)-(i>1);
b[i+1]-=a[i+2]*a[i+3];
b[i+1]-=a[i+2]*(a[i]+1);
}
cout<<"! ";
for(int i=1; i<=n; i++) cout<<a[i]<<" ";
cout<<endl<<endl;
}