T1:
只考虑
r
1
≤
r
2
r1\le r2
r1≤r2的,另外反过来做即可
考虑四种情况
1
:
1:
1:左下右
显然是
(
r
2
−
r
1
)
+
(
c
≠
0
)
+
c
2
(r2-r1)+(c\not=0)+c2
(r2−r1)+(c=0)+c2
2
:
2:
2:下(右)左
在
r
2
r2
r2处处理
维护一个单调递增的栈
找到
r
1
r1
r1后第一个栈内元素
p
p
p
c
h
e
m
n
(
c
1
,
a
p
)
chemn(c1,a_p)
chemn(c1,ap)
如果不向右靠直接下去
就是
(
r
2
−
r
1
)
+
(
c
2
−
c
1
)
(r2-r1)+(c2-c1)
(r2−r1)+(c2−c1)
否则是
(
r
2
−
r
1
)
+
min
k
(
∣
a
k
−
c
2
∣
)
(r2-r1)+\min_k(|a_k-c2|)
(r2−r1)+mink(∣ak−c2∣)
在栈内二分找到可能作为答案的
k
k
k计算即可
3
:
3:
3:上(右)下
同样在
c
2
c2
c2处理
二分找到第一个
≤
r
1
\le r1
≤r1的位置
那么就是这前面的一段
对于
a
p
≤
c
2
a_p\le c2
ap≤c2
贡献是
r
1
+
r
2
−
2
p
+
c
2
−
a
p
r1+r2-2p+c2-a_p
r1+r2−2p+c2−ap直接找第一个
a
p
<
c
2
a_p<c2
ap<c2就是了
否则贡献是
r
1
+
r
2
−
2
p
+
a
p
−
c
2
+
(
c
1
>
a
p
)
r1+r2-2p+a_p-c2+(c1>a_p)
r1+r2−2p+ap−c2+(c1>ap)
对于
c
1
≤
a
p
c1\le a_p
c1≤ap和
c
1
>
a
p
c1>a_p
c1>ap分别计算,都是一段区间
线段树维护
a
p
−
2
p
a_p-2p
ap−2p的最小值
4
:
4:
4:下(右)上
首先
c
1
c1
c1可能会在
[
r
1
,
r
2
]
[r1,r2]
[r1,r2]变小,
c
h
e
m
n
chemn
chemn个区间最小值
从后往前维护一个递增栈
然后讨论类似
3
3
3
这个反着做一次即可
复杂度 O ( ( n + q ) l o g n ) O((n+q)logn) O((n+q)logn)
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline int readstring(char *s){
int top=0;char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
s[top+1]='\0';return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int N=400005,INF=1061109567;
int n,a[N],q;
namespace Seg{
cs int N=::N<<2;
int mn[N];
#define lc (u<<1)
#define rc ((u<<1)|1)
#define mid ((l+r)>>1)
int st,des,p,k;
void build(){
memset(mn,127/2,sizeof(mn));
st=des=p=k=0;
}
inline void pushup(int u){
mn[u]=min(mn[lc],mn[rc]);
}
void update(int u,int l,int r){
if(l==r){mn[u]=k;return;}
if(p<=mid)update(lc,l,mid);
else update(rc,mid+1,r);
pushup(u);
}
void delet(int u,int l,int r){
if(l==r){mn[u]=INF;return;}
if(p<=mid)delet(lc,l,mid);
else delet(rc,mid+1,r);
pushup(u);
}
int query(int u,int l,int r){
if(des<l||st>r||st>des)return INF;
if(st<=l&&r<=des)return mn[u];
if(des<=mid)return query(lc,l,mid);
if(mid<st)return query(rc,mid+1,r);
return min(query(lc,l,mid),query(rc,mid+1,r));
}
void update(int _p,int _k){p=_p,k=_k,update(1,1,n);}
void delet(int _p){p=_p,delet(1,1,n);}
int query(int _st,int _des){st=_st,des=_des;return query(1,1,n);}
#undef lc
#undef rc
#undef mid
}
int ans[N];
struct ask{
int r1,c1,r2,c2,id;
};
int st[20][N],lg[N];
inline void buildst(){
for(int i=1;i<=n;i++)st[0][i]=a[i];
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j+(1<<i)-1<=n;j++)
st[i][j]=min(st[i-1][j],st[i-1][j+(1<<(i-1))]);
}
inline int querymn(int l,int r){
int t=lg[r-l+1];
return min(st[t][l],st[t][r-(1<<t)+1]);
}
int stk[N],top;
vector<ask>q1[N],q2[N],q3[N];
inline int Lower(int l,int r,int k){
int res=-1;
while(l<=r){
int mid=(l+r)>>1;
if(stk[mid]>=k)res=mid,r=mid-1;
else l=mid+1;
}return res;
}
inline int Less(int l,int r,int k){
int res=-1;
while(l<=r){
int mid=(l+r)>>1;
if(stk[mid]<=k)res=mid,l=mid+1;
else r=mid-1;
}return res;
}
inline int Lower2(int l,int r,int k){
int res=-1;
while(l<=r){
int mid=(l+r)>>1;
if(a[stk[mid]]>=k)res=mid,r=mid-1;
else l=mid+1;
}return res;
}
inline int Less2(int l,int r,int k){
int res=-1;
while(l<=r){
int mid=(l+r)>>1;
if(a[stk[mid]]<=k)res=mid,l=mid+1;
else r=mid-1;
}return res;
}
inline int calc1(int r1,int c1,int r2,int c2){
int ps=Lower(1,top,r1);
assert(ps!=-1);
int p=stk[ps],res=INF;
chemn(c1,a[p]);
chemn(res,(r2-r1)+abs(c2-c1));
p=Lower2(ps,top,c2);
if(p!=-1)chemn(res,(r2-r1)+1+abs(a[stk[p]]-c2));
p=Less2(ps,top,c2);
if(p!=-1)chemn(res,1+(r2-r1)+abs(a[stk[p]]-c2));
return res;
}
inline int calc2(int r1,int c1,int r2,int c2){
int ps=Less(1,top,r1);
if(ps==-1)return INF;
int p=Less2(1,ps,c2),res=INF;
if(p!=-1)chemn(res,r1+r2-2*stk[p]+c2-a[stk[p]]+(a[stk[p]]>c1));
if(p==-1)p=0;p++;
int pp=Less2(p,ps,c1);
if(pp!=-1&&p<=pp)chemn(res,Seg::query(stk[p],stk[pp])+r1+r2-c2);
if(pp==-1)pp=p-1;pp++;
if(pp<=ps)chemn(res,Seg::query(stk[pp],stk[ps])+r1+r2-c2+1);
return res;
}
inline int calc3(int r1,int c1,int r2,int c2){
int p=Less2(1,top,c2),res=INF;
if(p!=-1)chemn(res,2*stk[p]-a[stk[p]]-r1-r2+c2+(a[stk[p]]>c1));
if(p==-1)p=0;p++;
int pp=Less2(p,top,c1);
if(pp!=-1&&p<=pp)chemn(res,Seg::query(stk[pp],stk[p])-r1-r2-c2);
if(pp==-1)pp=p-1;pp++;
if(pp<=top)chemn(res,Seg::query(stk[top],stk[pp])-r1-r2-c2+1);
return res;
}
inline void solve(cs vector<ask> &q){
Seg::build(),buildst();
top=0;
for(ask x:q){
q1[x.r2].pb(x);
chemn(x.c1,querymn(x.r1,x.r2));
q2[x.r2].pb(x);
}
for(int i=1;i<=n;i++){
while(top&&a[i]<=a[stk[top]])Seg::delet(stk[top--]);
stk[++top]=i,Seg::update(i,a[i]-2*i);
for(cs ask &x:q1[i])
chemn(ans[x.id],calc1(x.r1,x.c1,x.r2,x.c2)),chemn(ans[x.id],calc2(x.r1,x.c1,x.r2,x.c2));
q1[i].clear();
}
top=0;Seg::build();
for(int i=n;i;i--){
while(top&&a[i]<=a[stk[top]])Seg::delet(stk[top--]);
stk[++top]=i,Seg::update(i,2*i+a[i]);
for(ask x:q2[i]){
chemn(ans[x.id],calc3(x.r1,x.c1,x.r2,x.c2));
}
q2[i].clear();
}
}
vector<ask> qr[2];
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
freopen("my.out","w",stdout);
#endif
n=read();
for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
for(int i=1;i<=n;i++)a[i]=read();
q=read();
for(int i=1;i<=q;i++){
int r1=read(),c1=read(),r2=read(),c2=read();
if(r1<=r2)
qr[0].pb(ask{r1,c1,r2,c2,i});
else qr[1].pb(ask{n-r1+1,c1,n-r2+1,c2,i});
ans[i]=abs(r1-r2)+c2+(c1!=0);
}
solve(qr[0]);
reverse(a+1,a+n+1);
solve(qr[1]);
for(int i=1;i<=q;i++)cout<<ans[i]<<"\n";return 0;
}
T2:
c
f
528
D
cf528D
cf528D
直接看每个字符能不能匹配每个位置
f
f
t
fft
fft处理通配即可
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline int readstring(char *s){
int top=0;char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
s[top+1]='\0';return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int mod=998244353;
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)?(a-b+mod):(a-b);}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){a=(a+b)>=mod?(a+b-mod):(a+b);}
inline void Dec(int &a,int b){a=(a<b)?(a-b+mod):(a-b);}
inline void Mul(int &a,int b){static ll r;r=(ll)a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(ll x){x%=mod;return (x<0)?x+mod:x;}
typedef vector<int> poly;
namespace Poly{
cs int C=21,M=(1<<C)|1;
int rev[M],*w[C+1];
inline void init_w(){
int wn=ksm(3,(mod-1)/(1<<C));
for(int i=1;i<=C;i++)w[i]=new int[(1<<(i-1))|1];
w[C][0]=1;
for(int i=1,l=(1<<(C-1));i<l;i++)w[C][i]=mul(w[C][i-1],wn);
for(int i=C-1;i;i--)
for(int j=0,l=1<<(i-1);j<l;j++)
w[i][j]=w[i+1][j<<1];
}
inline void init_rev(int lim){
for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)*(lim>>1));
}
inline void ntt(int *f,int lim,int kd){
for(int i=0;i<lim;i++)if(i>rev[i])swap(f[i],f[rev[i]]);
for(int mid=1,l=1,a0,a1;mid<lim;mid<<=1,l++)
for(int i=0;i<lim;i+=mid<<1)
for(int j=0;j<mid;j++)
a0=f[i+j],a1=mul(w[l][j],f[i+j+mid]),f[i+j]=add(a0,a1),f[i+j+mid]=dec(a0,a1);
if(kd==-1){
reverse(f+1,f+lim);
for(int i=0,iv=Inv(lim);i<lim;i++)Mul(f[i],iv);
}
}
inline poly operator *(poly a,poly b){
int deg=a.size()+b.size()-1;
if(a.size()<=16||b.size()<=16){
poly c(deg,0);
for(int i=0;i<a.size();i++)
for(int j=0;j<b.size();j++)
Add(c[i+j],mul(a[i],b[j]));
return c;
}int lim=1; while(lim<deg)lim<<=1;
init_rev(lim);
a.resize(lim),ntt(&a[0],lim,1);
b.resize(lim),ntt(&b[0],lim,1);
for(int i=0;i<lim;i++)Mul(a[i],b[i]);
ntt(&a[0],lim,-1),a.resize(deg);
return a;
}
}
using namespace Poly;
cs int N=500005;
int n,m,k;
char s[N],t[N];
int f[N],ss[N][4],ok[4][N];
inline int id(char x){
if(x=='A')return 0;
if(x=='T')return 1;
if(x=='G')return 2;
return 3;
}
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
init_w();
n=read(),m=read(),k=read();
readstring(s);
readstring(t);
for(int i=1;i<=n;i++){
memcpy(ss[i],ss[i-1],sizeof(ss[i-1]));
ss[i][id(s[i])]++;
}
for(int i=1;i<=n;i++){
for(int t=0;t<4;t++)if(ss[min(n,i+k)][t]-ss[max(0,i-k-1)][t]>0)ok[t][i]=1;
}
for(int c=0;c<4;c++){
poly a(n+1),b(m+1);
for(int i=1;i<=n;i++)a[i]=ok[c][i];
for(int i=1;i<=m;i++)b[m-i+1]=(id(t[i])==c);
a=a*b;
for(int j=1;j<=n-m+1;j++)f[j]+=a[j+m];
}int res=0;
for(int j=1;j<=n-m+1;j++)res+=f[j]==m;
cout<<res<<'\n';return 0;
}
T3:
O
(
n
2
l
o
g
)
O(n^2log)
O(n2log)的做法也比较显然吧
要么交在一个点要么都在一个面,面处理一下平行的特殊情况即可
但是很难写
于是直接判是否有交点跑最大团即可
跑的飞快
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define ll long long
#define pii pair<int,int>
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?res:-res;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){b=min(a,b);}
typedef double db;
cs db eps=1e-8;
inline int sign(db x){return (x>eps)-(x<-eps);}
struct pt{
db x,y,z;
pt(db _x=0,db _y=0,db _z=0):x(_x),y(_y),z(_z){}
friend inline pt operator +(cs pt &a,cs pt &b){
return pt(a.x+b.x,a.y+b.y,a.z+b.z);
}
friend inline pt operator -(cs pt &a,cs pt &b){
return pt(a.x-b.x,a.y-b.y,a.z-b.z);
}
friend inline pt operator *(cs pt &a,cs db &b){
return pt(a.x*b,a.y*b,a.z*b);
}
friend inline pt operator *(cs pt &a,cs pt &b){
return pt(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}
friend inline double operator ^(pt a,pt b){
return a.x*b.x+a.y*b.y+a.z*b.z;
}
friend inline bool operator <(cs pt &a,cs pt &b){
return (sign(a.x-b.x)==0)?((sign(a.y-b.y)==0)?(sign(a.z-b.z)==-1):(sign(a.y-b.y)==-1)):(sign(a.x-b.x)==-1);
}
friend inline bool operator ==(cs pt &a,cs pt &b){
return (sign(a.x-b.x)==0)&&(sign(a.y-b.y)==0)&&(sign(a.z-b.z)==0);
}
inline double len()cs{return (*this)^(*this);}
};
struct Pt{
db x,y;
Pt(db _x=0,db _y=0):x(_x),y(_y){}
friend inline Pt operator +(cs Pt &a,cs Pt &b){
return Pt(a.x+b.x,a.y+b.y);
}
friend inline Pt operator -(cs Pt &a,cs Pt &b){
return Pt(a.x-b.x,a.y-b.y);
}
friend inline db operator *(cs Pt &a,cs Pt &b){
return a.x*b.y-a.y*b.x;
}
friend inline Pt operator *(cs Pt &a,cs db &b){
return Pt(a.x*b,a.y*b);
}
friend inline bool operator <(cs Pt &a,cs Pt &b){
return (sign(a.x-b.x)==0)?(sign(a.y-b.y)==-1):(sign(a.x-b.x)==-1);
}
friend inline bool operator ==(cs Pt &a,cs Pt &b){
return (sign(a.x-b.x)==0)&&(sign(a.y-b.y)==0);
}
inline double dis(){return sqrt(x*x+y*y);}
};
cs int N=2005,M=N*N/2;
struct line{
pt s,t;
}ln[N];
inline bool Inter(cs line &a,cs line &b){
pt R1=a.s,R2=b.s,V1=(a.t-a.s),V2=(b.t-b.s);
if((V1*V2).len()==0)return false;
Pt s1(a.s.x,a.s.y),t1(a.t.x,a.t.y),s2(b.s.x,b.s.y),t2(b.t.x,b.t.y);
double v1=(s2-s1)*(t1-s1),v2=(t1-s1)*(t2-s1);
pt is1=b.s+(b.t-b.s)*(v1/(v1+v2));
v1=(s2-s1)*(t2-s1),v2=(t1-s2)*(t2-s2);
pt is2=a.s+(a.t-a.s)*(v1/(v1+v2));
return is1==is2;
}
int n,ans;
bool e[N][N];
int lk[N][N];
void dfs(int pos,int cnt,int now){
if(now+cnt<=ans)return;
chemx(ans,now);
//cout<<"bg\n";
int u=lk[pos][1],*c=lk[pos],*d=lk[pos+1];
// cout<<pos<<" "<<cnt<<" "<<now<<'\n';
for(int i=1;i<=cnt;i++){
int v=c[i],nc=0;
// cout<<v<<'\n';
if(e[u][v])continue;
for(int j=1;j<i;j++)if(e[u][c[j]]&&e[v][c[j]])d[++nc]=c[j];
for(int j=i+1;j<=cnt;j++)if(e[v][c[j]])d[++nc]=c[j];
dfs(pos+1,nc,now+1);
}
//cout<<"end\n";
}
int main(){
n=read();
for(int i=1;i<=n;i++){
ln[i].s.x=read();ln[i].s.y=read();ln[i].s.z=read();
ln[i].t.x=read();ln[i].t.y=read();ln[i].t.z=read();
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++){
if(Inter(ln[i],ln[j])){e[i][j]=e[j][i]=1;}
}
for(int i=1;i<=n;i++)lk[0][i]=i;
dfs(0,n,0);cout<<ans<<'\n';
return 0;
}
T4:
b z o j 5284 bzoj5284 bzoj5284
考虑直接
D
P
DP
DP需要
d
p
o
f
d
p
dp\ of\ dp
dp of dp做
记一下当前根选不选的最大独立集
如果记成
不
选
/
选
或
不
选
不选/选或不选
不选/选或不选的话可以发现
不
选
≤
选
或
不
选
≤
不
选
+
1
不选\le 选或不选 \le 不选+1
不选≤选或不选≤不选+1
于是设
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示
i
i
i个点,
不
选
不选
不选为
j
j
j,
选
或
不
选
选或不选
选或不选为
j
+
1
j+1
j+1的方案数
g
[
i
]
[
j
]
g[i][j]
g[i][j]为
不
选
/
选
或
不
选
不选/选或不选
不选/选或不选都为
j
j
j的方案数
如果第二维写成生成函数
转移就是
f
i
=
∑
j
f
i
−
j
g
j
f_i=\sum_jf_{i-j}g_j
fi=∑jfi−jgj
g
i
=
∑
j
g
j
g
i
−
j
+
g
i
−
j
f
j
x
+
f
i
−
j
f
j
x
g_i=\sum_{j}g_jg_{i-j}+g_{i-j}f_jx+f_{i-j}f_jx
gi=∑jgjgi−j+gi−jfjx+fi−jfjx
这个稍微想想独立集
d
p
dp
dp就可以明白
第二维用卷积优化即可
先转成点值最后再
I
D
F
T
IDFT
IDFT回去可以做到
O
(
n
3
)
O(n^3)
O(n3)
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int mod=998244353;
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)?(a-b+mod):(a-b);}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){a=(a+b)>=mod?(a+b-mod):(a+b);}
inline void Dec(int &a,int b){a=(a<b)?(a-b+mod):(a-b);}
inline void Mul(int &a,int b){static ll r;r=(ll)a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(ll x){x%=mod;return (x<0)?x+mod:x;}
cs int C=9,N=521,M=(1<<C)|1;
int rev[M],*w[C+1];
inline void init_w(){
int wn=ksm(3,(mod-1)/(1<<C));
for(int i=1;i<=C;i++)w[i]=new int[(1<<(i-1))|1];
w[C][0]=1;
for(int i=1,l=(1<<(C-1));i<l;i++)w[C][i]=mul(w[C][i-1],wn);
for(int i=C-1;i;i--)
for(int j=0,l=1<<(i-1);j<l;j++)
w[i][j]=w[i+1][j<<1];
}
inline void init_rev(int lim){
for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)*(lim>>1));
}
inline void ntt(int *f,int lim,int kd){
for(int i=0;i<lim;i++)if(i>rev[i])swap(f[i],f[rev[i]]);
for(int mid=1,l=1,a0,a1;mid<lim;mid<<=1,l++)
for(int i=0;i<lim;i+=mid<<1)
for(int j=0;j<mid;j++)
a0=f[i+j],a1=mul(w[l][j],f[i+j+mid]),f[i+j]=add(a0,a1),f[i+j+mid]=dec(a0,a1);
if(kd==-1){
reverse(f+1,f+lim);
for(int i=0,iv=Inv(lim);i<lim;i++)Mul(f[i],iv);
}
}
int n,m,lim,f[N][N],g[N][N],xf[N][N],x[N];
inline void Inc(int *f,int *a,int *b){
for(int i=0;i<lim;i++)Add(f[i],mul(a[i],b[i]));
}
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=read();
lim=1;while(lim<n)lim<<=1;
init_w();init_rev(lim);
f[1][0]=1,x[1]=1;
ntt(f[1],lim,1),ntt(x,lim,1);
Inc(xf[1],x,f[1]);
for(int i=2;i<=n;i++){
for(int j=1;j<i;j++){
Inc(f[i],f[i-j],g[j]);
Inc(g[i],g[i-j],g[j]);
Inc(g[i],g[i-j],xf[j]);
Inc(g[i],f[i-j],xf[j]);
}Inc(xf[i],x,f[i]);
}
for(int i=1;i<=n;i++){
ntt(f[i],lim,-1),ntt(g[i],lim,-1);
cout<<g[i][0]<<" ";
for(int j=1;j<=n;j++)cout<<add(g[i][j],f[i][j-1])<<" ";puts("");
}
}
一个优化是可以发现最中间乘了四次
而
g
g
g可以利用加起来乘了减去就只用乘
2
2
2次
另外一个优化是考虑独立集和最大匹配是相对的
于是改成
d
p
dp
dp最大匹配,而最大匹配数只有
n
/
2
n/2
n/2
这样最后一维只有
n
/
2
n/2
n/2的大小
不过最后输出需要注意一下
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int mod=998244353;
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)?(a-b+mod):(a-b);}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){a=(a+b)>=mod?(a+b-mod):(a+b);}
inline void Dec(int &a,int b){a=(a<b)?(a-b+mod):(a-b);}
inline void Mul(int &a,int b){static ll r;r=(ll)a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(ll x){x%=mod;return (x<0)?x+mod:x;}
cs int C=9,N=521,M=(1<<C)|1;
int rev[M],iv,*w[C+1];
inline void init_w(){
int wn=ksm(3,(mod-1)/(1<<C));
for(int i=1;i<=C;i++)w[i]=new int[(1<<(i-1))|1];
w[C][0]=1;
for(int i=1,l=(1<<(C-1));i<l;i++)w[C][i]=mul(w[C][i-1],wn);
for(int i=C-1;i;i--)
for(int j=0,l=1<<(i-1);j<l;j++)
w[i][j]=w[i+1][j<<1];
}
inline void init_rev(int lim){
for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)*(lim>>1));
}
inline void ntt(int *f,int lim,int kd){
for(int i=0;i<lim;i++)if(i>rev[i])swap(f[i],f[rev[i]]);
for(int mid=1,l=1,a0,a1;mid<lim;mid<<=1,l++)
for(int i=0;i<lim;i+=mid<<1)
for(int j=0;j<mid;j++)
a0=f[i+j],a1=mul(w[l][j],f[i+j+mid]),f[i+j]=add(a0,a1),f[i+j+mid]=dec(a0,a1);
if(kd==-1){
reverse(f+1,f+lim);
for(int i=0;i<lim;i++)Mul(f[i],iv);
}
}
int n,m,lim,f[N][N],g[N][N],xf[N][N],X[N];
inline void Inc(int *f,int *a,int *b){
for(int i=0;i<lim;i++)Add(f[i],mul(a[i],b[i]));
}
ll x[N],y[N];
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=read();
lim=1;while(lim<(n/2+1))lim<<=1;
init_w();init_rev(lim);
iv=Inv(lim);
g[1][0]=1,X[1]=1;
ntt(g[1],lim,1),ntt(X,lim,1);
int *a,*b,*c,*d;
for(int i=2;i<=n;i++){
for(int j=1;j<i;j++){
a=g[i-j],b=f[i-j],c=xf[j],d=g[j];
for(int k=0,tp;k<lim;k++)
tp=mul(a[k],c[k]),
x[k]+=(ll)(a[k]+b[k])*(c[k]+d[k])%mod-tp,
y[k]+=tp;
}a=f[i],b=g[i];
for(int j=0;j<lim;j++)a[j]=fix(x[j]),b[j]=fix(y[j]),x[j]=y[j]=0;
Inc(xf[i],X,f[i]);
}
for(int i=1;i<=n;i++){
ntt(f[i],lim,-1),ntt(g[i],lim,-1);
for(int j=i;j;j--)cout<<add(g[i][j],f[i][j-1])<<" ";
cout<<g[i][0]<<" ";
for(int j=i+1;j<=n;j++)cout<<0<<" ";
puts("");
}
}
另外: