zoukankan      html  css  js  c++  java
  • UVALive 7472

    题意 有n个循环 给出x a b c xi+1=(a*x+b)%c 要求是从这些循环中各取一个数 使加和最大并且给出一个m 满足sum%m!=0

    n的范围是4次方 c的范围是3次方 训练赛的时候看了一眼就觉得好难 稍微一处理就要超时..

    天气好热 又wa了水题两次 十分不想做题QAQ 看着有点难就懒得想 掏出手机开始玩 坑了蕾姐一把 QAQ 以后再也不这样了

    然而蕾姐还是机智的想出了几近正解的办法QAQ 

    在这个循环中 每两个紧挨着的数的间隔必定是一样的 这些数的值在0~C之间 是1000 

    我们对每个循环的最大值和次大值进行保存 

    可以看出 一旦出现sum%m 由于每个循环必定需要一个数 如果这个间隔%m==0 那么我们将一个大的数换为一个小的数 仍然会有sum%m==0 是浪费

    如果间隔%m!=0 那么换次大值就可以达到使sum%m==0变为!=0

    所以 我们把所有循环的最大值加起来作为一个sum 之后 找出最小且%k!=0的间隔

    如果sum%m!=0直接输出就可以 如果==0 就减去间隔 由于间隔%k!=0 所以减去间隔的sum%k!=0

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<math.h>
    #include<iostream>
    using namespace std;
    /// 保存下来 每个循环的循环大小(最大的和第二大的) 以及该循环是否可以%k 记录最大的和第二大的地点
    int xh[10050];
    int maxw1[10050];
    int maxw2[10050];
    int vis[1050];
    bool ok[10050];
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(ok,false,sizeof(ok));
            memset(vis,0,sizeof(vis));
            int x,a,b,c;
            int sum=0;
            for(int i=1; i<=n; i++)
            {
                scanf("%d%d%d%d",&x,&a,&b,&c);
                vis[x]=i;
                int maxx=x;
                int maxx2=-1;
                int maxxid=1;
                int maxx2id=-1;
                int cnt=1;
                while(1)
                {
                    x=(a*x+b)%c;
                    if(vis[x]==i)
                        break;
                    vis[x]=i;
                    cnt++;
                    if(x>maxx)
                    {
                        maxx2=maxx;
                        maxx=x;
                        maxx2id=maxxid;
                        maxxid=cnt;
                    }
                    else if(x>maxx2)
                    {
                        maxx2=x;
                        maxx2id=cnt;
                    }
                }
                maxw1[i]=maxxid;
                if(maxx2!=-1)
                {
                    maxw2[i]=maxx2id;
                    int z=maxx-maxx2;
                    xh[i]=z;
                    if(z%m!=0)
                        ok[i]=true;
                    else ok[i]=false;
                }
                else
                {
                    ok[i]=false;
                }
                sum+=maxx;
            }
            if(sum%m!=0)
            {
                printf("%d
    ",sum);
                for(int i=1; i<=n; i++)
                {
                    printf("%d",maxw1[i]-1);
                    if(i==n)
                        printf("
    ");
                    else printf(" ");
                }
            }
            else
            {
                int minn=1005;
                int w=-1;
                for(int i=1; i<=n; i++)
                {
                    if(ok[i])
                    {
                        if(xh[i]<minn)
                        {
                            minn=xh[i];
                            w=i;
                        }
                    }
                }
                if(minn!=1005)
                {
                    maxw1[w]=maxw2[w];
                    printf("%d
    ",sum-xh[w]);
                    for(int i=1; i<=n; i++)
                    {
                        printf("%d",maxw1[i]-1);
                        if(i==n)
                            printf("
    ");
                        else printf(" ");
                    }
                }
                else
                {
                    printf("-1
    ");
                }
            }
        }
    }
    

      

  • 相关阅读:
    53. Maximum Subarray
    64. Minimum Path Sum
    28. Implement strStr()
    26. Remove Duplicates from Sorted Array
    21. Merge Two Sorted Lists
    14. Longest Common Prefix
    7. Reverse Integer
    412. Fizz Buzz
    linux_修改域名(centos)
    linux_redis常用数据类型操作
  • 原文地址:https://www.cnblogs.com/rayrayrainrain/p/5736992.html
Copyright © 2011-2022 走看看