考虑记出欧拉回路图后任意断/连边都可行
而 D P DP DP只需要考虑简单容斥一下即可
#include
using namespace std;
#define cs const
#define pb push_back
#define ll long long
#define pii pair
#define fi first
#define se second
#define bg begin
cs int RLEN=(1<<20)|3;
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;
}
inline ll readll(){
char ch=gc();
ll 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;
}
inline int readstring(char *s){
char ch=gc();int l=0;
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++l]=ch,ch=gc();
return l;
}
inline char readchar(){
char ch=gc();
while(isspace(ch))ch=gc();return ch;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a<b?a=b:0;}
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)?(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);}
cs int N=2005;
int fac[N],ifac[N],f[N],g[N],n;
inline void init_fac(){
fac[0]=ifac[0]=1;
for(int i=1;i<N;i++)fac[i]=mul(fac[i-1],i);
ifac[N-1]=Inv(fac[N-1]);
for(int i=N-2;i;i--)ifac[i]=mul(ifac[i+1],i+1);
}
inline int C(int n,int m){return (n<m||n<0||m<0)?0:mul(fac[n],mul(ifac[m],ifac[n-m]));}
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
init_fac(),n=read();
g[1]=f[1]=1;
for(int i=2;i<=n;i++)f[i]=g[i]=ksm(2,(ll)(i-1)*(i-2)/2);
for(int i=2;i<=n;i++)
for(int j=1;j<i;j++)Dec(f[i],mul(C(i-1,j-1),mul(f[j],g[i-j])));
cout<<mul(n*(n-1)>>1,f[n])<<'\n';return 0;
}
以每个格子左上角跑出的最短路树一定不会被走的路径断开
然后每个格子拆成四个角四个点表位置然后跑 d i j dij dij即可
#include
using namespace std;
#define cs const
#define pb push_back
#define ll long long
#define pii pair
#define fi first
#define se second
#define bg begin
cs int RLEN=(1<<20)|3;
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;
}
inline ll readll(){
char ch=gc();
ll 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;
}
inline int readstring(char *s){
char ch=gc();int l=0;
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++l]=ch,ch=gc();
return l;
}
inline char readchar(){
char ch=gc();
while(isspace(ch))ch=gc();return ch;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a<b?a=b:0;}
cs int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
cs int N=405,M=N*N*4*2;
int adj[M],nxt[M<<1],to[M<<1],val[M<<1],ecnt;
inline void addedge(int u,int v,int w){
if(!u||!v)return;
nxt[++ecnt]=adj[u],adj[u]=ecnt,to[ecnt]=v,val[ecnt]=w;
nxt[++ecnt]=adj[v],adj[v]=ecnt,to[ecnt]=u,val[ecnt]=w;
}
bool vis[N][N],ok[N][N][4],t[N][N],vt[N*N*4];
int n,m,ln[N][N],rw[N][N],pre[N][N],id[N][N][4],tot;
ll d[N][N],dis[N*N*4];
inline int ID(int x,int y){return x*(m+2)+y;}
typedef pair<ll,int> pl;
priority_queue<pl,vector<pl>,greater<pl> > q;
inline int VAL(int x,int y,int d){
switch(d){
case 0:return ln[x-1][y];
case 1:return ln[x][y];
case 2:return rw[x][y-1];
case 3:return rw[x][y];
}
}
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=read(),m=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)t[i][j]=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m+1;j++)ln[i][j]=read();
for(int i=1;i<=n+1;i++)
for(int j=1;j<=m;j++)rw[i][j]=read();
for(int i=1;i<=n+1;i++)
for(int j=1;j<=m+1;j++)
for(int k=0;k<4;k++)
id[i][j][k]=++tot;
memset(dis,127/3,sizeof(dis));
memset(d,127/3,sizeof(d));
d[1][1]=0;
q.push(pl(0,ID(1,1)));
while(q.size()){
int x=q.top().se/(m+2),y=q.top().se%(m+2);
q.pop();if(vis[x][y])continue;
vis[x][y]=1;
for(int i=0;i<4;i++){
int px=x+dx[i],py=y+dy[i];
if(px<1||px>n+1||py<1||py>m+1)continue;
ll dt=d[x][y]+VAL(x,y,i);
if(dt<d[px][py]){
d[px][py]=dt,pre[px][py]=i^1,q.push(pl(dt,ID(px,py)));
}
}
}memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)if(t[i][j]){
int x=i,y=j;
id[i][j][2]=id[i][j+1][3]=id[i+1][j][1]=id[i+1][j+1][0]=0;
while(!vis[x][y]&&(x!=1||y!=1)){
vis[x][y]=1;int d=pre[x][y];
ok[x][y][d]=1,x+=dx[d],y+=dy[d];
ok[x][y][d^1]=1;
}
}id[1][1][0]=0;
for(int i=1;i<=n+1;i++)
for(int j=1;j<=m+1;j++){
if(!ok[i][j][0])addedge(id[i][j][0],id[i][j][1],0);
if(!ok[i][j][1])addedge(id[i][j][3],id[i][j][2],0);
if(!ok[i][j][2])addedge(id[i][j][0],id[i][j][3],0);
if(!ok[i][j][3])addedge(id[i][j][1],id[i][j][2],0);
}
for(int i=1;i<=n+1;i++)
for(int j=1;j<=m;j++)
addedge(id[i][j][1],id[i][j+1][0],rw[i][j]),
addedge(id[i][j][2],id[i][j+1][3],rw[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m+1;j++)
addedge(id[i][j][2],id[i+1][j][1],ln[i][j]),
addedge(id[i][j][3],id[i+1][j][0],ln[i][j]);
dis[id[1][1][1]]=0,q.push(pl(0,id[1][1][1]));
while(q.size()){
int u=q.top().se;q.pop();
if(vt[u])continue;
vt[u]=1;
for(int e=adj[u],v;e;e=nxt[e])if(dis[v=to[e]]>dis[u]+val[e]){
dis[v]=dis[u]+val[e];
q.push(pl(dis[v],v));
}
}cout<<dis[id[1][1][3]]<<'\n';
return 0;
}
考虑看做 n n n个颜色球,每个有 a i a_i ai个,有编号
每个颜色必须编号 1 1 1在最前面
这样方案数就是 m ! ∏ s \frac{m!}{\prod s} ∏sm!
现在相当于不考虑第一个出现的球的限制
枚举每一个然后容斥,枚举后面有几个 1 1 1,直接 D P DP DP即可
似乎按照 l d x ldx ldx的教育,用多项式实现可以做到两个 l o g log log?
分治ntt是两个,平衡结合似乎可以一个log
#include
using namespace std;
#define cs const
#define pb push_back
#define ll long long
#define pii pair
#define fi first
#define se second
#define bg begin
cs int RLEN=(1<<20)|3;
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;
}
inline ll readll(){
char ch=gc();
ll 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;
}
inline int readstring(char *s){
char ch=gc();int l=0;
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++l]=ch,ch=gc();
return l;
}
inline char readchar(){
char ch=gc();
while(isspace(ch))ch=gc();return ch;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a<b?a=b:0;}
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)?(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);}
cs int N=1005,M=55;
int fac[N],ifac[N],iv[N];
inline void init_C(){
fac[0]=ifac[0]=1;
for(int i=1;i<N;i++)fac[i]=mul(fac[i-1],i);
ifac[N-1]=Inv(fac[N-1]);
for(int i=N-2;i;i--)ifac[i]=mul(ifac[i+1],i+1);
iv[0]=iv[1]=1;
for(int i=2;i<N;i++)iv[i]=mul(mod-mod/i,iv[mod%i]);
}
inline int C(int n,int m){return (n<m||n<0||m<0)?0:mul(fac[n],mul(ifac[m],ifac[n-m]));}
int n,m,a[M];
int f[N];
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
init_C();n=read();
int res=0,pr=1;
for(int i=1;i<=n;i++)a[i]=read(),m+=a[i],Mul(pr,iv[a[i]]);
for(int p=1;p<=n;p++){
int s=0;
memset(f,0,sizeof(f));
f[a[p]]=1,s=a[p];
for(int i=1;i<=n;i++)if(i^p){
for(int j=s;~j;j--)
Dec(f[j+a[i]],f[j]);
s+=a[i];
}
int now=0;
for(int i=a[p];i<=m;i++)
Add(now,mul(f[i],mul(fac[m],iv[i])));
Add(res,mul(now,mul(pr,mul(a[p],a[p]))));
}cout<<res<<'\n';return 0;
}