由于全是SB题,简述如下:
T1:
请你求出有多少个长度为 n n n 字符集为 k k k 的串,本质不同子串个数为 m m m。
n ≤ 10 n\leq 10 n≤10
题解:
本质不同子串个数只和最小表示有关,爆搜然后算即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
cs int mod=1e9+7;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a-b<0?a-b+mod:a-b;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline void Inc(int &a,int b){a+=b-mod;a+=a>>31&mod;}
inline void Dec(int &a,int b){a-=b;a+=a>>31&mod;}
inline void Mul(int &a,int b){a=mul(a,b);}
int n,m,k,dn[15];
int s[15],ans;
namespace SAM{
cs int N=30;
int fa[N],len[N],nw;
int son[N][11],substr;
void ins(int i,int c){
int cur=i,p=(i-1)?(i-1):(n+1);
for(;p&&!son[p][c];p=fa[p])
son[p][c]=cur;
if(!p)fa[cur]=n+1;
else {
int q=son[p][c];
if(len[q]==len[p]+1)fa[cur]=q;
else {
int nq=++nw,q=son[p][c];
memcpy(son[nq],son[q],sizeof son[q]);
len[nq]=len[p]+1,fa[nq]=fa[q];
fa[q]=fa[cur]=nq;
for(;p&&son[p][c]==q;p=fa[p])
son[p][c]=nq;
}
}substr+=len[cur]-len[fa[cur]];
}
void solve(int sz){
while(nw){
fa[nw]=len[nw]=0;
memset(son[nw],0,sizeof son[nw]);
--nw;
}substr=0;nw=n+1;
for(int re i=1;i<=n;++i)
len[i]=i;
for(int re i=1;i<=n;++i)
ins(i,s[i]);
if(substr==m)Inc(ans,dn[sz]);
}
}
void dfs(int nw,int mx){
if(nw==n+1){
SAM::solve(mx);
return ;
}for(int i=1;i<=mx+1;++i)
s[nw]=i,dfs(nw+1,std::max(mx,i));
}
void Main(){
scanf("%d%d%d",&n,&m,&k);
for(int re i=dn[0]=1;i<=n;++i)
dn[i]=mul(dn[i-1],k-i+1);
dfs(1,0);cout<<ans<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("string.in","r",stdin);
#else
#ifndef ONLINE_JUDGE
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
#endif
#endif
}signed main(){file();Main();return 0;}
T2:
CC 原题,随机化+最小斯坦纳树。
出题人说过 没有任何已知的贪心解法,你要说乱搞那。。。
反正榜上一大堆贪心过的,当时我造了组数据全hack,现在那组数据已经找不到了。。。
T3:
跳跳棋魔改版,计数。
题解:
由于 k k k 不大,找LCA可以暴力。
考虑移动起点, 不能移动终点。
设终点到根的距离为 d d d, d p [ k ] [ i ] [ j ] dp[k][i][j] dp[k][i][j] 表示走 k k k 步结束,当前 S S S 距离 LCA i i i 条边 , T T T 距离LCA j j j 条边的方案数。
SB DP题。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
cs int mod=1e9+7;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a-b<0?a-b+mod:a-b;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline void Inc(int &a,int b){a+=b-mod;a+=a>>31&mod;}
inline void Dec(int &a,int b){a-=b;a+=a>>31&mod;}
inline void Mul(int &a,int b){a=mul(a,b);}
struct atom{
ll a,b,c;atom(){}
atom(ll _a,ll _b,ll _c):a(_a),b(_b),c(_c){}
bool stop(){return b-a==c-b;}
atom jump(){
if(b-a<c-b)
return atom(b,b+b-a,c);
else
return atom(a,b+b-c,b);
}void get(){scanf("%lld%lld%lld",&a,&b,&c);}
friend bool operator==(cs atom &a,cs atom &b){
return a.a==b.a&&a.b==b.b&&a.c==b.c;
}
};
cs int N=1e2+7;
int k;
atom s1[N],s2[N];
int d1,d2;
int dp[N][N][N];
void Main(){
s1[0].get(),s2[0].get();
scanf("%d",&k);
while(d1<=k&&!s1[d1].stop())
s1[d1+1]=s1[d1].jump(),++d1;
while(d2<=k&&!s2[d2].stop())
s2[d2+1]=s2[d2].jump(),++d2;
dp[0][0][0]=1;
for(int re i=1;i<=k;++i){
dp[i][0][0]=add(dp[i-1][0][1],mul(2,dp[i-1][1][0]));
for(int re j=1;j<=d2;++j)
dp[i][0][j]=add(add(dp[i-1][0][j+1],dp[i-1][1][j]),dp[i-1][0][j-1]);
for(int re j=1;j<=k;++j)
for(int re l=0;l+j<=i;++l)
dp[i][j][l]=add(dp[i-1][j-1][l],mul(2,dp[i-1][j+1][l]));
}for(int re i=0;i<=d1;++i)
for(int re j=0;j<=d2;++j)
if(s1[i]==s2[j]){
cout<<dp[k][i][j]<<"\n";
return ;
}
cout<<0<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("rabbits.in","r",stdin);
#else
#ifndef ONLINE_JUDGE
freopen("rabbits.in","r",stdin);
freopen("rabbits.out","w",stdout);
#endif
#endif
}signed main(){file();Main();return 0;}