• 2018.7.23模拟考试


    天我居然A了一道题???怕不是把明年的运气都用光了

    T1 题意简述:给出两个n*n的矩阵,m次询问它们的积中给定子矩阵的数值和。

                 n<=2000,m<=50000

       解题思路:这道题其实最主要的是这个...每个测试点时限6秒

                 这告诉我们...暴力就能过...

                 当然也不能随便暴力。分别做前缀和即可。复杂度O(nm)。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<ctime>
    #define ll long long
    using namespace std;
    ll n,m;
    ll ans,suma[2010][2010],sumb[2010][2010];
    ll read()
    {
        ll f=1;ll x=0;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        x*=f;return x;
    }
    int main()
    {
    //    system("CreatRand.exe");
        freopen("matrix.in","r",stdin);
        freopen("matrix.out","w",stdout);
    //    ll st=clock();
        n=read(),m=read();
        for(ll i=1;i<=n;i++)
            for(ll j=1;j<=n;j++)
                suma[i][j]=read(),suma[i][j]+=suma[i-1][j];
        for(ll i=1;i<=n;i++)
            for(ll j=1;j<=n;j++)
                sumb[i][j]=read(),sumb[i][j]+=sumb[i][j-1];
        for(ll i=1;i<=m;i++)
        {
            ans=0;
            ll xa=read(),ya=read(),xb=read(),yb=read();
            if(xa>xb) swap(xa,xb);
            if(ya>yb) swap(ya,yb);
            for(ll i=1;i<=n;i++)
                ans+=(suma[xb][i]-suma[xa-1][i])*(sumb[i][yb]-sumb[i][ya-1]);
            printf("%lld
    ",ans);
        }
    //    ll ed=clock();
    //    printf("%lld
    ",ed-st);
        return 0;
    }

    T2 题意简述平面上有N个整数坐标点。如果将点(x0,y0)移动到(x1,y1),则代价为它们之间的切比雪

                 夫距离。求使得K个点在同一位置上最少需要的代价。

                 N≤50,K=(1,N),0≤xi≤yi≤10^6

       解题思路:有一条很显然的性质:这个同一位置的横坐标必与某个点的横坐标相同。纵坐标亦然。

                 至于怎么证明...感性理解就好。(略略略)

                 因此只需要枚举出所有满足条件的点(最多n^2个),分别求出其与n个坐标点的距离,排】

                 序后做前缀和,分别取最小值即可。

                 能这么做的原因是因为数据太水。正解似乎是平衡树。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<ctime>
    #define ll long long
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,cnt,dot[55][3],dis[2505][55];
    int main()
    {
        freopen("tower.in","r",stdin);
        freopen("tower.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&dot[i][1],&dot[i][2]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                cnt++;
                for(int k=1;k<=n;k++)
                    dis[cnt][k]=abs(dot[k][1]-dot[i][1])+abs(dot[k][2]-dot[j][2]);
                sort(dis[cnt]+1,dis[cnt]+1+n);
                for(int k=1;k<=n;k++)
                    dis[cnt][k]+=dis[cnt][k-1];
            }
        for(int i=1;i<=n;i++)
        {
            int ans=INF;
            for(int j=1;j<=cnt;j++)
                ans=min(ans,dis[j][i]);
            printf("%d
    ",ans);
        }
        return 0;
    }

    T3 题意简述:求一棵树的最大匹配及最大匹配种类数。

                 60%的数据:答案不超过10^18。100%的数据:N≤1000。

       解题思路:先得吐槽一下出题人...模拟赛出什么高精度...听AK大佬说普通的高精还过不了,得用

                 压位高精什么的...垃圾出题人

                 以下思路及代码仅适用于前60分。

                 考虑到匈牙利算法无法算出种类数,考虑树上算法。

                 扳了扳手指算了算发现这次考试还没有考dp,考虑树形dp。

                 f[i][0,1]表示以i为根的子树,f[i][0]表示点i未匹配的最大值,f[i][1]表示点i匹配

                 的最大值,g[i][0,1]表示相应的方案数。

                 f[i][0] = ∑max{f[i.son][0],f[i.son][1]}

                             g[i.son][0]            (f[i.son][0] > f[i.son][1])

                 g[i][0] = ∏g[i.son][1]            (f[i.son][0] < f[i.son][1])

                             g[i.son][0]+g[i.son][1](f[i.son][0] == f[i.son][1])

                 f[i][1] = max{f[i][0] - max(f[i.son][0],f[i.son][1]) + f[i.son][0]}+1

                 g[i][1] = f[i][1]时的方案数。

                 由于博主本人过菜,代码无法输出正确答案,这里贴出Menteur_Hxy大佬的代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    using namespace std;
    ll n,cnt,root,d[1005],head[1005];
    ll f[1005][2],g[1005][2];
    struct uio{
        ll nxt,to;
    }edge[1000005];
    void add(ll x,ll y)
    {
        edge[++cnt].nxt=head[x];
        edge[cnt].to=y;
        head[x]=cnt;
    }
    void dfs(ll x)
    {
        ll sum=0,mul=1;
            for(ll i=head[x];i;i=edge[i].nxt) { ll y=edge[i].to;
            dfs(y); 
            sum+=max(f[y][0],f[y][1]);
            if(f[y][0]>f[y][1]) mul*=g[y][0];
            else if(f[y][0]<f[y][1]) mul*=g[y][1];
            else mul*=(g[y][0]+g[y][1]);
        }
        f[x][0]=sum,g[x][0]=mul;
        for(ll i=head[x];i;i=edge[i].nxt) { ll y=edge[i].to;
            ll now=sum-max(f[y][0],f[y][1])+f[y][0]+1;
            if(now>f[x][1]) {
                f[x][1]=now;
                if(f[y][0]>f[y][1]) g[x][1]=mul;
                else if(f[y][0]<f[y][1]) g[x][1]=mul/g[y][1]*g[y][0];
                else g[x][1]=mul/(g[y][0]+g[y][1])*g[y][0];
            } else if(now==f[x][1]) {
                if(f[y][0]>f[y][1]) g[x][1]+=mul;
                else if(f[y][0]<f[y][1]) g[x][1]+=mul/g[y][1]*g[y][0];
                else g[x][1]+=mul/(g[y][0]+g[y][1])*g[y][0];
            }    
        }
    //    g[x][0]=1;f[x][0]=0;
    //    for(ll i=head[x];i;i=edge[i].nxt)
    //    {
    //        ll y=edge[i].to;
    //        dfs(y);
    //        f[x][0]+=max(f[y][0],f[y][1]);
    //        if(f[y][0]>f[y][1]) g[x][0]*=g[y][0];
    //        if(f[y][0]<f[y][1]) g[x][0]*=g[y][1];
    //        if(f[y][0]==f[y][1]) g[x][0]*=(g[y][0]+g[y][1]);
    //    }
    //    for(ll i=head[x];i;i=edge[i].nxt)
    //    {
    //        ll y=edge[i].to;
    //        ll now=f[x][0]-max(f[y][0],f[y][1])+f[y][0]+1;
    //        if(now>f[x][1])
    //        {
    //            f[x][1]=now;
    //            if(f[y][0]>f[y][1]) g[x][1]=g[x][0];
    //            if(f[y][0]<f[y][1]) g[x][1]=g[x][0]/g[y][1]*g[y][0];
    //            if(f[y][0]==f[y][1]) g[x][1]=g[x][0]/(g[y][0]+g[y][1])*g[y][0];
    //        }
    //        if(now==f[x][1])
    //        {
    //            if(f[y][0]>f[y][1]) g[x][1]+=g[x][0];
    //            if(f[y][0]<f[y][1]) g[x][1]+=g[x][0]/g[y][1]*g[y][0];
    //            if(f[y][0]==f[y][1]) g[x][1]+=g[x][0]/(g[y][0]+g[y][1])*g[y][0];
    //        }
    //    }
    }
    int main()
    {
    //    freopen("tree.in","r",stdin);
    //    freopen("tree.out","w",stdout);
        scanf("%lld",&n);
        for(ll i=1;i<=n;i++)
        {
            ll u,v,w;
            scanf("%lld%lld",&u,&v);
            for(ll j=1;j<=v;j++)
            {
                scanf("%lld",&w),
                add(u,w);d[w]++;
            }
        }
        for(ll i=1;i<=n;i++)
            if(!d[i]) {root=i;break;}
        dfs(root);
        printf("%lld
    ",max(f[root][0],f[root][1]));
        if(f[root][0]>f[root][1]) printf("%lld
    ",g[root][0]);
        if(f[root][0]<f[root][1]) printf("%lld
    ",g[root][1]);
        if(f[root][0]==f[root][1]) printf("%lld
    ",g[root][0]+g[root][1]);
        return 0;
    }
  • 相关阅读:
    函数
    文件处理及处理模式
    字符编码
    元组,字典和集合的用法
    数字类型、字符串和列表
    计算机硬件介绍
    数据类型及语法介绍
    初识python
    设计模式
    最近的时候
  • 原文地址:https://www.cnblogs.com/water-radish/p/9354902.html
Copyright © 2020-2023  润新知