• 10.25 考试


    T1

    太鼓达人...我会说我考试的时候想了半天打表吗?当然不会

    开大栈记得要点上执行命令...

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #define ll long long
    #define rint register int
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    
    int n,len,maxp;
    int zhan[(1<<20)+1000],he;
    bool flag[(1<<20)+1000];
    
    void dfs(int order,int now)
    {
        //printf("order=%d now=%d
    ",order,now);
        if(order==len+1)
        {
            if(!now)
            {
                for(int i=1;i<=len;++i)
                    printf("%d",zhan[i]);
                printf("
    ");
                exit(0);
            }
            return ;
        }
        if(flag[now])
            return ;
        flag[now]=1;
        
        int tt;
        
        tt=(((now<<1)&maxp)|1);
        zhan[++he]=1;
        dfs(order+1,tt);
        --he;
        
        tt=((now<<1)&maxp);
        zhan[++he]=0;
        dfs(order+1,tt);
        --he;
        
        flag[now]=0;
    }
    
    int main(){
        
        //freopen("T1biao.out","w",stdout);
        
        scanf("%d",&n);
        len=(1<<n); maxp=(1<<n)-1;
        dfs(1,0);
    }
    dfs代码

    迭代code (你现在应该知道我有多懒了...)

    T2

    树规...

    状态数组:

    $f_{i,j} 以第i个结点为根的子树走了j个点又回到i的最小花费$

    $g_{i,j} 以第i个结点为根的子树走了j个点在任意点停下的最小花费$

    然后进行背包就行了,记得枚举已有子树大小和当前加入子树大小,不要在外面枚举总的大小

    #pragma GCC optimize("O3")
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #define ll long long
    #define rint register int
    #define mem(a,b) memset(a,b,sizeof(a))
    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=10006;
    int first[N*2],nt[N*2],w[N*2],ver[N*2],e;
    void addbian(int u,int v,int _w)
    {
        w[e]=_w; ver[e]=v;
        nt[e]=first[u];
        first[u]=e++;
    }
    
    int n,K,root;
    int f[N][N];// 走回来 
    int g[N][N];// 不走回来 
    
    int fa[N],size[N];
    void dfs(int x)
    {
        size[x]=1;
        f[x][0]=f[x][1]=0;
        g[x][0]=g[x][1]=0;
        int i,j,k,t1,t2;
        for(i=first[x];i!=-1;i=nt[i])
        {
            if(ver[i]==fa[x]) continue;
            fa[ver[i]]=x;
            dfs(ver[i]);
            
            for(j=(size[x]<K?size[x]:K);j;--j)
                for(k=0;k<=size[ver[i]];++k)
                {
                    if(j+k>K)
                        break;
                    t1=f[x][j]+f[ver[i]][k]+w[i]*2;
                    if(f[x][j+k]>t1) f[x][j+k]=t1;
                    t1=g[x][j]+f[ver[i]][k]+w[i]*2; t2=f[x][j]+g[ver[i]][k]+w[i];
                    if(t1>t2) t1=t2;
                    if(g[x][j+k]>t1) g[x][j+k]=t1;
                }
            size[x]+=size[ver[i]];
        }
    }
    
    int main(){
        
        //freopen("T2.in","r",stdin);
        //freopen("T2.out","w",stdout);
        rint i,j;
        
        mem(first,-1);
        
        read(n); read(K); read(root);
        int tin1,tin2,tin3;
        for(i=1;i<n;++i)
        {
            read(tin1); read(tin2); read(tin3);
            addbian(tin1,tin2,tin3);
            addbian(tin2,tin1,tin3);
        }
        mem(f,60); mem(g,60);
        dfs(root);
        cout<<g[root][K];
    }
    T2

    T3

    因子个数相同,显然将阶乘分解质因数,然后暴搜

    首先你需要一个map记忆化,在搜的时候边乘边除gcd,使它们互质

    因为相同的约数是无用的,这样不仅可以减少map的结点,还会变快

    然后剪枝

    发现2、3、5的数量很多,所以可以预处理出来,每个数对的数量,再开一个map存下来

    假设当前dfs的数对是 A,B 它们互质,那么2、3、5贡献的数对必须是 B,A 才会相等

    所以正确

    还有一个剪枝

    大的素数只有一个,所以可以跳过,在最后枚举用组合数计算

    但是我没用,因为记忆化搜索够快了

    /*
    我认为把因子个数是1的跳过,在最后处理并不会加快
    因为记忆化搜索不会因为这个慢... 
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #include <map>
    #define ll long long
    #define rint register int
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ull unsigned long long
    #define dd double
    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();
    }
    ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}
    int intgcd(int x,int y){return y==0?x:gcd(y,x%y);}
    
    struct son
    {
        ll s1,s2;
        son(){}
        son(ll _s1,ll _s2)
        {
            s1=_s1; s2=_s2;
        }
        bool friend operator < (son a,son b)
        {
            if(a.s1==b.s1)
                return a.s2<b.s2;
            return a.s1<b.s1;
        }
    };
    
    int n;
    int num[28];
    int prime[106],cnt,top;
    bool he[106];
    map<son,ll> mp[26];
    map<son,int> mm;
    void dfs1(int order,int A,int B)
    {
        int gg=intgcd(A,B);
        A/=gg; B/=gg;
        if(order==top+1)
        {
            // 这里不能A大B小,不然会重复 
            ++mm[son(A,B)];
            return ;
        }
        for(int i=0;i<=num[order];++i)
            dfs1(order+1,A*(i+1),B*(num[order]-i+1));
    }
    void chu()
    {
        rint i,j;
        
        for(i=2;i<=n;++i)
        {
            if(!he[i])
                prime[++cnt]=i;
            for(j=1;j<=cnt&&i*prime[j]<=n;++j)
            {
                he[i*prime[j]]=1;
                if(i%prime[j]==0)
                    break;
            }
        }
        int tt;
        for(i=1;i<=n;++i)
        {
            tt=i;
            for(j=1;j<=cnt;++j)
                while(tt%prime[j]==0)
                {
                    ++num[j];
                    tt/=prime[j];
                }
        }
        top=min(3,cnt);
        dfs1(1,1,1);
    }
    
    ll dfs(int order,ll A,ll B)
    {
        ll gg=gcd(A,B);
        A/=gg; B/=gg;
        if(A>B) A^=B,B^=A,A^=B; // A大B小可以优化掉一半 
        son hh=(son){A,B};
        if(order==top)
        {
            if(mm.count(hh))
                return mm[hh];
            return 0;
        }
        if(mp[order].count(hh))
            return mp[order][hh];
        ll as=0;
        for(int i=num[order];i>=0;--i)
            as+=dfs(order-1,A*(i+1),B*(num[order]-i+1));
        mp[order][hh]=as;
        return as;
    }
    
    int main(){    
        rint i,j;
        read(n);
        if(n==1)
        {
            printf("1");
            return 0;
        }
        chu();
        printf("%lld",dfs(cnt,1,1)/2);
    }
    T3
  • 相关阅读:
    015.Python基础--模块
    014.Python基础--格式化输入输出
    013.Python基础--异常/错误处理
    012.Python基础--装饰器深入
    011.Python基础--装饰器
    010.Python基础--生成器
    汇编的角度分析指针-03(字符串深入理解)
    汇编的角度分析C语言的指针-02
    汇编的角度分析C语言的switch语句
    分析C语言的字节对齐
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7731863.html
Copyright © 2020-2023  润新知