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;
inline void read(int &x)
{
    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;
void addbian(int u,int v)
{
    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);
    
    read(n);
    int tin1,tin2;
    for(i=1;i<n;++i)
    {
        read(tin1); read(tin2);
        addbian(tin1,tin2);
        addbian(tin2,tin1);
    }
    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

题解释哈夫曼树,然而我并不是这样想的...

可以考虑在01trie上行走

那么它一定是在每一个深度都用完了,在到下一层

可以脑补一下...

#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;
inline void read(int &x)
{
    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();
    
    read(n);
    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;
inline void read(int &x)
{
    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);
    
    read(n); read(K);
    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;
inline void read(int &x)
{
    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);
    
    read(n); read(K);
    printf("%lld",dp());
}
2

(3)

$O(nK^2)$ 的dp

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

特别的,差值j是当前走的路线到过了最大值和最小值才行,所以不会重复

#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;
inline void read(int &x)
{
    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(){
    
    read(n); read(K);
    printf("%lld",dp());
}
3

(4)

$O(nK)$ 的dp

我们考虑在一个n*K大小的网格里从最左边往右走

枚举起点在最左边的位置,就相当于枚举最小值

$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;
inline void read(int &x)
{
    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(){
    
    read(n); read(K);
    printf("%lld",dp());
}
4

 

posted @ 2017-10-28 21:39  A_LEAF  阅读(179)  评论(0编辑  收藏  举报