zoukankan      html  css  js  c++  java
  • CodeForces Round #257 (Div. 2)

    题目:

    A Jzzhu and Children          ------    CodeForces 450A

    B Jzzhu and Sequences     ------    CodeForces 450B

    C Jzzhu and Chocolate       ------   CodeForces 449A

    D Jzzhu and Cities              ------    CodeForces 449B

    E Jzzhu and Apples            ------    CodeForces 449C


    A题:n个数字每次从前到后每一个数字-m  问哪个数字最后减到0  (水题)


    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    typedef __int64 LL;
    #define N 100010
    
    int n,m,ans;
    
    int main()
    {
        int i,x,y;
        scanf("%d%d",&n,&m);
        for(i=1,y=-1;i<=n;i++)
        {
            scanf("%d",&x);
            if(x/m+(x%m!=0)>=y)
            {
                y=x/m+(x%m!=0);
                ans=i;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }


    B题:定义序列f1 = x , f2 = y , fi = fi-1 + fi+1  问第n项%1e9+7等于几 (简单数学题)

    将递推公式变形 fi = fi-1 - fi-2 则能够推出循环节为6  然后直接计算


    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    typedef __int64 LL;
    #define N 100010
    #define mod 1000000007
    
    LL x,y,n,ans;
    
    int main()
    {
        scanf("%I64d%I64d%I64d",&x,&y,&n);
        n%=6;
        switch(n)
        {
            case 0: ans=x-y; break;
            case 1: ans=x; break;
            case 2: ans=y; break;
            case 3: ans=y-x; break;
            case 4: ans=-x; break;
            case 5: ans=-y; break;
        }
        printf("%I64d
    ",(ans%mod+mod)%mod);
        return 0;
    }

    C题:切巧克力  仅仅能在凹进去的地方横切或者竖切  问  n*m的巧克力切k刀后最小块面积最大能有多大 (想法题)

    首先假设k比n+m-2大  一定输出-1

    接着考虑切的策略  为了使最小块最大  我们应该尽量少分几份

    那么就是说尽量在一个方向切(要么都横切要么都竖切)

    然后開始讨论  假设在一个方向能把k刀都切掉  那么推断一下是横切优还是竖切优

    最后  假设一个方向切不下k刀  那么必定要两个方向都切

    非常明显应该先切长边  由于这样切分的块数最少


    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef __int64 LL;
    
    LL n,m,k;
    
    int main()
    {
        scanf("%I64d%I64d%I64d",&n,&m,&k);
        if(n+m-2<k) printf("-1
    ");
        else if(n%(k+1)==0||m%(k+1)==0) printf("%I64d
    ",n*m/(k+1));
        else
        {
            if(n<m) swap(n,m);
            if(m-1>=k) printf("%I64d
    ",max(m/(k+1)*n,n/(k+1)*m));
            else if(n-1>=k) printf("%I64d
    ",n/(k+1)*m);
            else printf("%I64d
    ",m/(k-n+2));
        }
        return 0;
    }

    D题:n个城市之间有公路和铁路  每条路都是双向的且长度已知  铁路一定是从1城市到某个城市  如今要删掉尽量多的铁路线  但要保持1城市到每一个城市的最短路径不变  问最多删几条 (图论题)

    由于要多删铁路线  所以能走公路就走公路  但要保证最短路径不变

    由此得出策略  我们从1城市開始做最短路  依照能走公路就走公路的原则求完整幅图的最短路  这时在最短路径上的铁路线就是不能够被删去的  那么删去的条数计算一下就可以


    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    typedef __int64 LL;
    #define N 100010
    
    int n,m,k,tot,ans;
    int vis[N],head[N],pre[N];
    LL dis[N];
    struct edge
    {
        int v,w,kind,next;
    }ed[N*8];
    struct node
    {
        int idx;
        LL dis;
        bool operator<(const node fa) const
        {
            return dis>fa.dis;
        }
    }u,v;
    priority_queue<node> qu;
    
    void add(int u,int v,int w,int kind)
    {
        ed[tot].v=v;
        ed[tot].w=w;
        ed[tot].kind=kind;
        ed[tot].next=head[u];
        head[u]=tot++;
    }
    
    void bfs()
    {
        int i;
        u.dis=0; u.idx=1;
        qu.push(u);
        while(!qu.empty())
        {
            do
            {
                u=qu.top();
                qu.pop();
            }while(vis[u.idx]&&!qu.empty());
            if(vis[u.idx]) return ;
            vis[u.idx]=1;
            if(pre[u.idx]!=-1) ans+=ed[pre[u.idx]].kind;
            for(i=head[u.idx];~i;i=ed[i].next)
            {
                v.idx=ed[i].v;
                v.dis=u.dis+ed[i].w;
                if(!vis[v.idx])
                {
                    if(dis[v.idx]==v.dis&&!ed[i].kind) pre[v.idx]=i;
                    if(!dis[v.idx]||dis[v.idx]>v.dis)
                    {
                        pre[v.idx]=i;
                        dis[v.idx]=v.dis;
                        qu.push(v);
                    }
                }
            }
        }
    }
    
    int main()
    {
        int i,u,v,w;
        memset(head,-1,sizeof(head));
        memset(pre,-1,sizeof(pre));
        scanf("%d%d%d",&n,&m,&k);
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w,0);
            add(v,u,w,0);
        }
        for(i=1;i<=k;i++)
        {
            scanf("%d%d",&v,&w);
            add(1,v,w,1);
        }
        bfs();
        printf("%d
    ",k-ans);
        return 0;
    }

    E题:有1到n的数字  为它们两两分一组  要求分在一组的数字不互素  问最多分几组  并给出方案(数论题)

    偶数对我们来说是最友好的  由于全部的偶数都能够组队  奇数里的素数尤其不友好

    利用上述想法能够枚举素数(不是从2開始  是从3開始)  将因子包括该素数的数字所有找出来

    这时假设有偶数个数  那么直接能够两两分组

    假设有奇数个数(但不是一个)  那么我们从里面扔掉一个偶数  之后两两分组

    最后剩下的数要么是找不到分组的数  要么是偶数  我们将偶数两两分组  就得出了答案


    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    typedef __int64 LL;
    #define N 100010
    
    int n,cnt,ans;
    int flag[N],p[N],vis[N];
    vector< pair<int,int> > v;
    
    void get_prime()
    {
        int i,j;
        for(i=2;i<=n;i++)
        {
            if(!flag[i]) p[cnt++]=i;
            for(j=0;j<cnt&&p[j]*i<=n;j++)
            {
                flag[i*p[j]]=1;
                if(i%p[j]==0) break;
            }
        }
    }
    
    int main()
    {
        int i,j,k;
        scanf("%d",&n);
        get_prime();
        for(i=1;i<cnt;i++)
        {
            vector<int> tmp;
            for(j=p[i];j<=n;j+=p[i])
            {
                if(!vis[j]) tmp.push_back(j);
            }
            k=tmp.size();
            if(k==1) continue;
            if(k%2==1)
            {
                for(vector<int>::iterator it=tmp.begin();it!=tmp.end();it++)
                {
                    if(*it%2==0)
                    {
                        tmp.erase(it);
                        k--;
                        break;
                    }
                }
            }
            for(j=0;j<k;j+=2)
            {
                vis[tmp[j]]=1;
                vis[tmp[j+1]]=1;
                v.push_back(make_pair(tmp[j],tmp[j+1]));
                ans++;
            }
        }
        for(i=2,j=0;i<=n;i+=2)
        {
            if(!vis[i])
            {
                if(j)
                {
                    v.push_back(make_pair(j,i));
                    ans++;
                    j=0;
                }
                else j=i;
            }
        }
        printf("%d
    ",ans);
        for(i=0;i<ans;i++) printf("%d %d
    ",v[i].first,v[i].second);
        return 0;
    }

    PS:昨天逃掉了比赛今天才来补题TAT  要鞭策自己更加勤奋才行!!!

  • 相关阅读:
    Spring+Spring MVC+Hibernate框架搭建实例
    数据结构:串
    为什么java中用枚举实现单例模式会更好
    验证码原理分析及实现
    Servlet监听器——实现在线登录人数统计小例子
    IntelliJ IDEA 远程调试 Tomcat 的方法
    SQL注入的一些技巧分享
    Java中String与byte[]的转换
    JavaSE基础:集合类
    二叉树的非递归遍历
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4024794.html
Copyright © 2011-2022 走看看