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;
}

 

posted on 2011-12-21 22:19  Lattexiaoyu  阅读(254)  评论(0编辑  收藏  举报

导航