zoukankan      html  css  js  c++  java
  • noip2014Day2解题报告

    1.无线网络发射器选址

    题目::https://www.luogu.org/problem/show?pid=2038

    题解::第一题水题,直接枚举放的位置,用二维前缀和维护一下,注意一下边界就行了。时间复杂度O(129^2);

    代码::

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    template<class T>inline void read(T &x)
    {
        x=0;int f=0;char ch=getchar();
        while(ch<'0'||ch>'9')f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;
        return;
    } 
    int sum[200][200],num[200][200];
    int main()
    {
        int d,n,x,y,k,t=0,ans=0;
        read(d);read(n);
        for(int i=1;i<=n;i++)
        {
            read(x);read(y);read(k);
            num[x+1][y+1]=k;
        }
        for(int i=1;i<=129;i++)
        for(int j=1;j<=129;j++)
        sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+num[i][j];
        for(int i=1;i<=129;i++)
        for(int j=1;j<=129;j++)
        {
            int x1=min(129,i+d),y1=min(129,j+d),x2=max(0,i-d-1),y2=max(0,j-d-1);
            if(sum[x1][y1]+sum[x2][y2]-sum[x1][y2]-sum[x2][y1]>ans)
            {
                ans=sum[x1][y1]+sum[x2][y2]-sum[x1][y2]-sum[x2][y1];
                t=1;
            }
            else if(sum[x1][y1]+sum[x2][y2]-sum[x1][y2]-sum[x2][y1]==ans)t++;
        }
        printf("%d %d\n",t,ans);
        return 0;
    }

    2.寻找道路

    题目::https://www.luogu.org/problem/show?pid=2296

    题解::先反向建边bfs求出所有与终点不联通的点,在枚举每个点的每条边的终点是否联通,判断出可以在路径上的点,最后跑一边最短路就可以了;

    代码::

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 10010
    #define inf 2000000010
    using namespace std;
    template<class T>inline void read(T &x)
    {
        x=0;int f=0;char ch=getchar();
        while(ch<'0'||ch>'9')f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;
        return;
    } 
    struct node{int v,next;}e[200100],E[200100];
    int cnt,head[maxn],Head[maxn],d[maxn],q[1000100],n,m;
    bool vis[maxn],can[maxn];
    void ins(int u,int v){e[++cnt].v=v;e[cnt].next=head[u];head[u]=cnt;}
    void Ins(int u,int v){E[cnt].v=v;E[cnt].next=Head[u];Head[u]=cnt;}
    void bfs(int s)
    {
        vis[s]=true;
        int h=0,t=0;q[0]=s;
        while(h<=t)
        {
            int u=q[h++];
            for(int p=Head[u];p;p=E[p].next)
            {
                int v=E[p].v;
                if(!vis[v])q[++t]=v,vis[v]=true;
            }
        }
    }
    void init()
    {
        memset(can,true,sizeof(can));
        for(int i=1;i<=n;i++)
        if(!vis[i])can[i]=false;
        else for(int p=head[i];p;p=e[p].next)
        {
            int v=e[p].v;
            if(!vis[v])can[i]=false;    
        }
    }
    int spfa(int s,int T)
    {
        memset(vis,false,sizeof(vis));
        memset(d,0x7f,sizeof(d));
        d[s]=0;vis[s]=true;q[0]=s;
        int h=0,t=0;
        while(h<=t)
        {
            int u=q[h++];
            for(int p=head[u];p;p=e[p].next)
            {
                int v=e[p].v;
                if(!can[v])continue;
                if(d[v]>d[u]+1)
                {
                    d[v]=d[u]+1;
                    if(!vis[v])vis[v]=true,q[++t]=v; 
                }
            }
            vis[u]=false;
        }
        if(d[T]>inf)return -1;
        else return d[T];
    }
    int main()
    {
        int x,y,s,t;
        read(n);read(m);
        for(int i=1;i<=m;i++)
        {
            read(x);read(y);ins(x,y);Ins(y,x);
        } 
        read(s);read(t);
        bfs(t);
        init();
        if(!can[s])printf("-1\n");
        else printf("%d\n",spfa(s,t));
        return 0;
    }

    3.解方程

    题目::https://www.luogu.org/problem/show?pid=2312

    题解::如果直接按照题目模拟,不仅时间复杂度上很难接受,而且要打高精度乘和高精度加,代码复杂度很大。那么我们该怎么办呢?我们可以想到如果一个数为0,那么这个数对任意一个数取余也为0,反过来却不一定,所以我们对这个数对很多的质数取余,

    如果都为0,那么这个数就是0,这些质数怎么选呢?我们选3到4个质数使他们的乘积大于m的最大值即可。这样做是O(nmk)k是质数的个数,这样是70分的。那么怎么办?

    如果有一个数x,他对一个质数p取余为y,那么x+p对p取余也为y,所以我们不需要枚举m个数,只需要枚举p-1个数(p是我们选的质数),这样就可以过了。

    tips:读入时,我们一位一位的读,同时取余,这样就不需要高精度了。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    long long a[110][6];
    char s;
    int ans[1000010],f[31010][3],cnt,n,m,mod[6]={10007,10917,30071};
    void read(int x)
    {
        long long ret=0,F=0,cnt=0;
        char ch=s;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')F=1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            for(int i=0;i<3;i++)a[x][i]=(a[x][i]*10+ch-'0')%mod[i];
            ch=getchar();
        }
        if(F)for(int i=0;i<3;i++)a[x][i]=mod[i]-a[x][i];
    }
    bool solve(long long x,int op)
    {
        long long sum=0;
        for(int i=n;i>=0;i--)sum=(a[i][op]+sum*x)%mod[op];
        return !sum;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;i++)read(i);
        for(int i=0;i<3;i++)
        for(int j=0;j<mod[i];j++)
            f[j][i]=solve(j,i);
        for(int i=1;i<=m;i++)
            if(f[i%mod[0]][0]&&f[i%mod[1]][1]&&f[i%mod[2]][2])ans[++cnt]=i;
        printf("%d\n",cnt);
        for(int i=1;i<=cnt;i++)printf("%d\n",ans[i]);
        return 0;
    }

    测试成绩:

    总分240

    第一题:70

    第二题:100

    第三题:70

    总结:

    第一题打二维前缀和时,边界判断错误,失掉了30分,这是不应该的,第一题失分说明自己对第一题的重视不够,太大意了,下次要记住教训。

    第二题思路比较清晰,打的也比较快,这也归功于平常的图论刷的比较多。别的类型的题刷的还是少了。

    第三题想的比较久,打的比较久,成绩也还行,差一点就想到正解了,数学题还是比较难,也没什么办法……

    这次测试总的来说做的还行,希望能继续保持下去。

  • 相关阅读:
    [DB] 数据库的连接
    JS leetcode 翻转字符串里的单词 题解分析
    JS leetcode 拥有最多糖果的孩子 题解分析,六一快乐。
    JS leetcode 搜索插入位置 题解分析
    JS leetcode 杨辉三角Ⅱ 题解分析
    JS leetcode 寻找数组的中心索引 题解分析
    JS leetcode 移除元素 题解分析
    JS leetcode 最大连续1的个数 题解分析
    JS leetcode 两数之和 II
    JS leetcode 反转字符串 题解分析
  • 原文地址:https://www.cnblogs.com/jiangtao0508/p/7719797.html
Copyright © 2011-2022 走看看