# 10.28 考试

T1

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define rint register int
using namespace std;
{
x=0; char q=getchar();
while(q<'0'||q>'9') q=getchar();
while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
const int N=100006;
int first[N],nt[N*2],ver[N*2],e;
{
ver[e]=v;
nt[e]=first[u];
first[u]=e++;
}

int n,an;

int fa[N],xi[N],id[N];
void dfs(int x)
{
xi[x]=1;
int i;
for(i=first[x];i!=-1;i=nt[i])
{
if(ver[i]==fa[x])
continue;
fa[ver[i]]=x;
id[ver[i]]=(i>>1)+1;
dfs(ver[i]);
xi[x]+=xi[ver[i]];
}
}

int main(){

//freopen("T1.in","r",stdin);

//freopen("div.in","r",stdin);
//freopen("div.out","w",stdout);

rint i;

mem(first,-1);

int tin1,tin2;
for(i=1;i<n;++i)
{
}
dfs(1);
an=-1;
for(i=1;i<=n;++i)
if(id[i]&&xi[i]*2==n)
an=id[i];
cout<<an;
fclose(stdin);
fclose(stdout);
}
T1

T2

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define rint register int
using namespace std;
{
x=0; char q=getchar();
while(q<'0'||q>'9') q=getchar();
while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
const int N=10000006;
const int mod=1000000007;

ll qpow(ll a,int ci)
{
ll ans=1;
while(ci)
{
if(ci&1)
ans=ans*a%mod;
a=a*a%mod;
ci>>=1;
}
return ans;
}

int n;

ll jie[N],jieni[N];
void chu()
{
int i;

jie[0]=1;
for(i=1;i<N;++i) jie[i]=jie[i-1]*i%mod;
jieni[N-1]=qpow(jie[N-1],mod-2)%mod;
for(i=N-2;i>=1;--i)
jieni[i]=jieni[i+1]*(i+1)%mod;
jieni[0]=1;
}

ll C(int n,int m)
{
if(n<0||m<0||n<m) return 0;
return jie[n]*jieni[m]%mod*jieni[n-m]%mod;
}

int main(){

//freopen("str.in","r",stdin);
//freopen("str.out","w",stdout);

chu();

int k=0;
while((1<<k)<=n) ++k; --k;
printf("%lld",C((1<<k),(n-(1<<k)))%mod*jie[n]%mod );
fclose(stdin);
fclose(stdout);
}
T2

T3

(1)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define rint register int
using namespace std;
{
x=0; char q=getchar();
while(q<'0'||q>'9') q=getchar();
while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
const int N=5006;
const int mod=1000000007;

int n,K;
int ans;

void dfs(int order,int now,int mn,int mx)
{
if(mx-mn>K)
return ;
if(order==n+1)
{
++ans;
return ;
}
dfs(order+1,now+1,mn,max(mx,now+1));
dfs(order+1,now+2,mn,max(mx,now+2));
dfs(order+1,now-1,min(mn,now-1),mx);
}

int main(){

//freopen("T3.in","r",stdin);

dfs(1,0,0,0);
cout<<ans;
}
1

(2)

$O(nK^3)$的dp

$f_{i,j,k,v}$ 表示当前走到了第i个位置，最大值是j，最小值是k，当前的权值是v的方案数

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define rint register int
using namespace std;
{
x=0; char q=getchar();
while(q<'0'||q>'9') q=getchar();
while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
const int N=5006;
const int mod=1000000007;
const int BAO=78;

int n,K;
ll f[2][BAO*3][BAO][BAO*2];

ll dp()
{
rint i,j,k,p;
int now=1,mn=BAO-n,mx=n+n+BAO,nx,tmx,tt;
//printf("mn=%d mx=%d\n",mn,mx);
mem(f,0);
f[0][BAO][BAO][0]=1;
for(i=0;i<n;++i)
{
now^=1; nx=now^1;
mem(f[nx],0);
for(j=mn;j<=mx;++j)
for(k=BAO-i;k<=j;++k)
for(p=max(j,BAO);p<=mx;++p)
if(f[now][j][k][p-BAO])
{
//printf("i=%d\n",i);
tmx=p-BAO; tt=f[now][j][k][tmx];
f[nx][j+1][k][max(tmx,j+1-BAO)]+=tt; f[nx][j+1][k][max(tmx,j+1-BAO)]%=mod;
f[nx][j+2][k][max(tmx,j+2-BAO)]+=tt; f[nx][j+2][k][max(tmx,j+2-BAO)]%=mod;
f[nx][j-1][min(j-1,k)][tmx]+=tt; f[nx][j-1][min(j-1,k)][tmx]%=mod;
}
}
ll ans=0;
for(i=mn;i<=mx;++i)
for(j=mn;j<=BAO;++j)
{
tt=min(j+K,mx);
for(k=j;k<=tt;++k)
ans=(ans+f[nx][i][j][k-BAO])%mod;
}
return ans;
}

int main(){

freopen("T3.in","r",stdin);

printf("%lld",dp());
}
2

(3)

$O(nK^2)$ 的dp

$f_{i,j,k}$ 表示当前走到了第i个位置，最大值和最小值的差值是j，当前值比最小值大k的方案数

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define rint register int
using namespace std;
{
x=0; char q=getchar();
while(q<'0'||q>'9') q=getchar();
while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
const int mod=1000000007;

int n,K;
ll f[2][306][306];

ll dp()
{
int i,j,k,tt,now=1,nx,nj,nk; ll ans=0;
f[0][0][0]=1;
for(i=0;i<n;++i)
{
now^=1; nx=now^1;
mem(f[nx],0);
for(j=0;j<=2*i&&j<=K;++j)
for(k=0;k<=j;++k)
if(f[now][j][k])
{
nk=k+1; nj=j; if(nj<nk) nj=nk;
if(nj<=K) f[nx][nj][nk]=(f[nx][nj][nk]+f[now][j][k])%mod;
nk=k+2; nj=j; if(nj<nk) nj=nk;
if(nj<=K) f[nx][nj][nk]=(f[nx][nj][nk]+f[now][j][k])%mod;
nk=k-1; nj=j; if(nk<0) nj=nj-nk,nk=0;
if(nj<=K) f[nx][nj][nk]=(f[nx][nj][nk]+f[now][j][k])%mod;
}
}
for(i=0;i<=K;++i)
for(j=0;j<=i;++j)
ans=(ans+f[nx][i][j])%mod;
return ans%mod;
}

int main(){

printf("%lld",dp());
}
3

(4)

$O(nK)$ 的dp

$f_{i,j,k}$ 表示当前走到了第i个位置，当前的权值是j，到没到过0(也就是最小值)的方案数

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define rint register int
using namespace std;
{
x=0; char q=getchar();
while(q<'0'||q>'9') q=getchar();
while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
}
const int mod=1000000007;

int n,K;
ll f[2][5006][2];

ll dp()
{
int i,j,k,tt,now=1,nx; ll ans=0;
f[0][0][1]=1;
for(i=1;i<=K;++i) f[0][i][0]=1;
for(i=0;i<n;++i)
{
now^=1; nx=now^1;
mem(f[nx],0);
for(j=0;j<=K;++j)
{
tt=j+1;
if(tt<=K) f[nx][tt][0]=(f[nx][tt][0]+f[now][j][0])%mod,f[nx][tt][1]=(f[nx][tt][1]+f[now][j][1])%mod;
tt=j+2;
if(tt<=K) f[nx][tt][0]=(f[nx][tt][0]+f[now][j][0])%mod,f[nx][tt][1]=(f[nx][tt][1]+f[now][j][1])%mod;
tt=j-1;
if(tt>0) f[nx][tt][0]=(f[nx][tt][0]+f[now][j][0])%mod,f[nx][tt][1]=(f[nx][tt][1]+f[now][j][1])%mod;
else if(tt==0) f[nx][tt][1]=(f[nx][tt][1]+f[now][j][0]+f[now][j][1])%mod;
}
}
for(i=0;i<=K;++i)
ans=(ans+f[nx][i][1])%mod;
return ans%mod;
}

int main(){

}