• Day5下


    T1

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    using namespace std;
    const int N=1010;
    int n,m,k,p;
    int to[N],nex[N];
    int a[N][N];
    int main()
    {
        freopen("rotate.in","r",stdin);
        freopen("rotate.out","w",stdout);
        scanf("%d%d%d",&n,&p,&k);
        for(int j=1;j<=n;j++)    to[j]=j;
        for(int i=1;i<=p;i++)
        {
            scanf("%d",&m);a[i][0]=m;
            for(int j=1;j<=m;j++)    scanf("%d",&a[i][j]);
        }
        for(int i=p;i>=1;i--)
        {
            memset(nex,0,sizeof nex);m=a[i][0];
            
            for(int j=2;j<=m;j++)    nex[a[i][j-1]]=a[i][j];
            nex[a[i][m]]=a[i][1];
            
            for(int j=1;j<=n;j++)
            if(nex[to[j]])    to[j]=nex[to[j]];
        }
        for(int j=1;j<=n;j++)
        printf("%d ",to[j]);
        return 0;
    }
    first 100

    置换,没学过的话模拟就行。考察理解题意了。

    正着做:置换的性质。(不知道也能做)

    T2

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    using namespace std;
    const int N=1e4+100;
    int n,a,b,c,d;
    int q[N];
    long long ans;
    int main()
    {
        freopen("range.in","r",stdin);
        freopen("range.out","w",stdout);
        scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
        
        for(int i=1;i<=n;i++) scanf("%d",&q[i]);
        
        for(int i=1,j;i<=n;i++)
        {
            int ans1,ans2;
            ans1=ans2=q[i];
            if(ans1<a||ans2>d)    continue;
            j=i;
            for(j;j<=n;j++)
            {
                ans1&=q[j];ans2|=q[j];
                if(ans1<a||ans2>d)    break;
                if(ans1<=b&&ans2>=c)    ans++;
            }
        }
        cout<<ans<<endl;
        return 0;
    } 
    first 60 
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<cmath>
    #include<ctime>
    using namespace std;
    typedef long long  LL;
    const int N=1e5+7;
    const LL P=1e9+7;
    LL ans;
    int s[N],sta[N][21],sto[N][21];
    int worka(int l,int r)
    {
        int L=r-l+1;
        int t=log2(L);
        return sta[l][t]&sta[r-(1<<t)+1][t];
    }
    int worko(int l,int r)
    {
        int L=r-l+1;
        int t=log2(L);
        return sto[l][t]|sto[r-(1<<t)+1][t];
    }
    int n,a,b,c,d;
    int main()
    {
        freopen("range.in","r",stdin);
        freopen("range-me.out","w",stdout);
        scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&s[i]);
            sta[i][0]=sto[i][0]=s[i];
        }
        
        //预处理倍增,下一步能O(1)查询区间值 
        for(int j=1;j<=20;j++)
        for(int i=1;i<=n;i++)
        if(i+(1<<j)-1 <=n )
        {
            sta[i][j]=sta[i][j-1]&sta[i+(1<<j)][j-1];
            sto[i][j]=sto[i][j-1]|sto[i+(1<<j)][j-1];
        }
        //查找区间(具有单调性)
        for(int i=1;i<=n;i++)
        {
            int andans,orans;
        //    andans=orans=s[i];
            int j=i;
            while(j<=n)
            {
                int L=j,R=n+1,mid;
                andans=worka(i,j);
                orans=worko(i,j);
                while(R-L>1)
                {
                    mid=(L+R)>>1;
                    if(worka(i,mid)==andans&&worko(i,mid)==orans)
                        L=mid;
                    else R=mid;
                }
                if(andans>=a&&andans<=b&& orans>=c&&orans<=d)
                ans+=L-j+1;
                j=L;
            } 
            
        } 
        cout<<ans%P;
    }
    二分+st优化 

    先固定左端典,向右搜,查找区间个数。

    怎么优化,二分 +倍增。

    本来我想’与‘和’或‘是不满足 前缀差等于区间值的性质的

    其实我的想法太狭隘了,仔细想想:无论是’与‘还是’或‘ 都满足两段区间O(1)合成更大区间的性质。

    比如f[1,6] & f[3,9],  可以看成f[1,3] & f[3,6]&f[6,9] &f[3,6] 一个数和本身的’‘与’还是本身无影响。

    然后就能通过二分把n^n变成nlogn,

    T3

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    using namespace std;
    const int N=1009;
    const int P=1e9+7;
    int n,k;
    int h[N],nex[N*2],to[N*2],cnt;
    int w[N],sum[N],tot[N];//子树节点数,根到这的和 
    int x,y;
    void add()
    {
        scanf("%d%d",&x,&y);
        to[++cnt]=y,nex[cnt]=h[x],h[x]=cnt;
        to[++cnt]=x,nex[cnt]=h[y],h[y]=cnt;
    }
    int vis[N];int ans;
    void dfs(int Tot,int Sum,int last)
    {
        if(Tot==k)
        {
            int ss=Sum;
            for(int i=1;i<=n;i++)
            if(vis[i])
            for(int j=h[i];j;j=nex[j])
            if(!vis[to[j]])        Sum++;
            Sum=n-1-Sum;
            ans=(1LL*ans+1LL*(1<<Sum)%P)%P;         
            
        
            Sum=ss;    
        }
        if(Tot>k)    return ;
        for(int i=last;i<=n;i++)
        if(vis[i])
        {
            int is=0;
            for(int j=h[i];j;j=nex[j])
            if(!vis[to[j]])    {
                vis[to[j]]=1;
                dfs(Tot+w[to[j]],Sum+1,i);
                vis[to[j]]=0;
            is=1;        
            }        
        }
    }
    int main()
    {
        freopen("fruit.in","r",stdin);
        freopen("fruit.out","w",stdout);
        scanf("%d%d",&n,&k);
        int is=1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&w[i]);
            if(!w[i])    is=0;
        }
        for(int i=1;i<n;i++)    add();
            
        vis[1]=1;
        dfs(w[1],0,1);
        if(!is) ans--;
        cout<<ans;
        return 0;
    }
    0分 
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef long long LL;
    const LL P= 1e9+7;
    const int N=1009;
    int n,k;
    int a[N];
    int h[N],nex[N*2],to[N*2],cnt;
    LL f[N][N];
    int x,y;
    void add()
    {
        scanf("%d%d",&x,&y);
        to[++cnt]=y,nex[cnt]=h[x],h[x]=cnt;
        to[++cnt]=x,nex[cnt]=h[y],h[y]=cnt;
    }
    int dfs(int x,int fa)
    {
        int sum=1,tmp;
        for(int i=h[x];i;i=nex[i])
        {
            if(to[i]==fa)    continue;
            for(int j=0;j<=n-a[to[i]];j++)
                f[to[i]][j+a[to[i]]]=f[x][j];
            tmp=dfs(to[i],x);
            for(int j=0;j<=n;j++)
            f[x][j]=(f[x][j]*(1<<(tmp-1))+f[to[i]][j])%P;
            sum+=tmp;
        }
        return sum;
    }
    int main()
    {
        freopen("d.in","r",stdin);
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<n;i++)    add();
        
        f[1][a[1]]=1;
        dfs(1,0);
        printf("%lld",(f[1][k]));
    }
    树上dp

    说到T3我就不得不吐槽一下,我投入了整套题考试总时间中超过一半的时间,结果0分。遗憾啊。

    搜索 搜重了,不知道怎么去重。

    正解是个背包(我没看出来。。。),f[i][j]表示在i节点及其子树中拿j个果子的方案数,。

    转移的话先遍历子节点,再根据已有信息更新其他字节点,和其父节点。

      dp[x][j] = ((1<<(tmp-1) * dp[x][j] % mod + dp[son][j])% mod

    (除了直接相连的边必须断掉之外,其他边怎样都行,2^n 种状态。

  • 相关阅读:
    B. Random Teams(Codeforces Round 273)
    Unity3d中的属性(Attributes)整理
    Python 的 Flask 框架安装应用
    动态SQL(章节摘要)
    Linux系统PWM驱动【转】
    嵌入式电路中的BUCK VS LDO【转】
    git用法-打补丁【转】
    展讯7731C_M Android6.0 充电指示灯实现(一)------关机充电实现【转】
    Android 充电信息的获取【转】
    2.Android硬件访问服务编写系统代码【转】
  • 原文地址:https://www.cnblogs.com/CLGYPYJ/p/7767961.html
Copyright © 2020-2023  润新知