• CDOJ1615 Sarmutation


      题目地址http://acm.uestc.edu.cn/problem.php?pid=1615

      题目分析:作者定义了一个序列Saya infinite series(简称Saries),我们用A(n)表示。A(n)由两个正整数Cd唯一确定。而定义方法则是一个递推关系,根据n mod 4的余数决定A(k)A(k-1)的关系:

    n mod 4 == 1A(k-1) + d --> A(k)

    n mod 4 == 2A(k-1) * d --> A(k)

    n mod 4 == 3A(k-1) - d --> A(k)

    n mod 4 == 0A(k-1) / d --> A(k) 

    我们现在分析下这个序列。假定我们选定了Cd,那么可以写出这个序列如下:

    C、      C+d、   (C+d*d、     (C+d-1*d

    C+d-1、 C+2d-1、 (C+2d-1*d、   (C+2d-2*d

    C+2d-2C+3d-2、 (C+3d-2*d、   (C+3d-3*d

    C+3d-3、 ... ...

    分析一下就会发现:

      1. A( 4*k+4 )总比A( 4*k )d-1!(d>=1的,我们发现子序列A(0)A(4)A(8)A(12) ... ...是单调不降的,且都是正整数)

      2. A(4*k+1)A(4*k+2)A(4*k+3) A(4*k)之间的关系是不变的,for all k,(就是说如果我们从A(4*k-1)将序列截断,从A(4*k)开始的子序列也是符合定义的Saries,此时新序列的C'==C+k*d-k);

      3. 因为d>=1,所以A(4*k+1)A(4*k+2)A(4*k+3) 不会比A(4*k)小!(给定这样一个序列,可以知道A(0)==C等于序列的最小值,所以我们能很快得到C值,至于d的值,见下面分析)

    作者又定义了一个序列Saya Sequence(简称Saquence),我们简称为S(n)S(n)A(n)中从能被4整除的n处截断的有限长序列(当然后面也要截断,不然就是无限长了)。经过上面分析2,我们不难分析出S(n)可以看做一个只在后面截断的A(n)S(0)==A(0)

    作者又定义一个S(n)的排列为Saya Permutation(简称为Sarmutation),我们叫做P(n)吧。题目让我们判断一个序列是否是一个P(n)

      解题思路P(n)看做一个被从n之后截断的A(n)的重排列。从P(n)中找出Cd然后重构出A(0)~A(n),判断P(0)~P(n)是否是A(0)~A(n)的重排列(这个建议大家把P(n)A(n)排序后匹配)。

    假定P(n)已按从小到大排好序。

    寻找C:见上面的分析3

    寻找d

    1. d==1,此时原来的A(n)不就成了:CC+1C+1CCC+1C+1CCC+1C+1C ... ...了吗?P(n)必然如下:CCCC ... ... C+1C+1C+1 ...... 具体判断方法见下面checkDEqualTo1()函数;

    2. d>1,此时很完美了!此时排序后的P(n)序列的第二小的元素将是C+d-1!而且C+d-1大于C(从上面我们列出的A(n)序列可以分析出来);具体判断方法见下面代码中checkDGreaterThan1()函数。

    Ps:若是序列元素个数小于5,最好特判。

    源代码

    #include<cstdio>
    #include<iostream>
    #include<algorithm>

    using namespace std;

    int p[1005],a[1005];

    bool cmp(int x,int y)
    {
    if(x<y)
    return true;
    return false;
    }

    bool checkDEqualTo1(int C,int d,int n)
    {
    int i,x,y;
    x=y=0;
    for(i=0; i<n; i++)
    {
    if(p[i]==C)
    x++;
    else if(p[i]==C+1)
    y++;
    else
    return false;
    }
    if(x==y || ((x==y+1 || x==y-1) && x%2==1))
    return true;
    return false;
    }

    bool checkDGreaterThan1(int C,int d,int n)
    {
    int i;
    a[0]=C;
    a[1]=C+d;
    for(i=2; i<n; i++)
    {
    if(i%4==1)
    a[i]=a[i-1]+d;
    else if(i%4==2)
    a[i]=a[i-1]*d;
    else if(i%4==3)
    a[i]=a[i-1]-d;
    else
    a[i]=a[i-1]/d;
    }
    sort(a,a+n,cmp);
    for(i=0; i<n; i++)
    {
    if(a[i]!=p[i])
    return false;
    }
    return true;
    }

    int main()
    {
    int T,n,i,C,d,sign;
    cin>>T;
    while(T--)
    {
    cin>>n;
    for(i=0; i<n; i++)
    scanf("%d",&p[i]);
    sort(p,p+n,cmp);

    if(n==2)//特判1:只有两个数C,C+d...
    {
    if(p[0]>0 && p[1]>p[0])
    sign=1;
    else
    sign=0;
    }
    else if(n==3)//特判2:三个数C,C+d,(C+d)*d
    {
    if(p[0]>0 && p[1]>p[0] && p[2]%p[1]==0 && p[2]/p[1]==p[1]-p[0])
    sign=1;
    else
    sign=0;
    }
    else if(n==4)//特判3:四个数C,C+d,(C+d)*d,(C+d-1)*d
    {
    if(p[0]>0 && ((p[0]==p[1] && p[1]==p[2]-1 && p[2]==p[3])/*d==1*/
    || (p[1]>p[0] && (d=p[1]-p[0]) && p[2]==(p[0]+d-1)*d && p[3]==(p[0]+d)*d)/*d>1*/))
    sign=1;
    else
    sign=0;
    }
    else //n>=5
    {
    if(p[0]>0 && p[1]==p[0] && (C=p[0],d=1) && checkDEqualTo1(C,d,n)==true)
    sign=1;
    else if(p[0]>0 && p[1]>p[0] && (C=p[0],d=p[1]-p[0]+1) && checkDGreaterThan1(C,d,n)==true)
    sign=1;
    else
    sign=0;
    }
    if(sign==1)
    printf("YES\n");
    else
    printf("NO\n");
    }
    return 0;
    }

     

  • 相关阅读:
    php生成xml文件头
    常用正则表达式
    数值数组排序
    《那些年啊,那些事——一个程序员的奋斗史》——97
    《那些年啊,那些事——一个程序员的奋斗史》——98
    《那些年啊,那些事——一个程序员的奋斗史》——99
    《那些年啊,那些事——一个程序员的奋斗史》——100
    《那些年啊,那些事——一个程序员的奋斗史》——100
    《那些年啊,那些事——一个程序员的奋斗史》——99
    《那些年啊,那些事——一个程序员的奋斗史》——98
  • 原文地址:https://www.cnblogs.com/Lattexiaoyu/p/2296395.html
Copyright © 2020-2023  润新知