CODEVS1006&&2081&&2205等差数列

复习dp,做了一系列的等差数列,突然发现第一个和第二个是穷举的。。。

1006:

题目描述  Description

给定n(1<=n<=100)个数,从中找出尽可能多的数使得他们能够组成一个等差数列.求最长的等差数列的长度.

 

思路:穷举,n^3的时间复杂度,稳过。

 

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[101]={0};
int main()
{
    int sum,ans=0,n,i,j,k,ch,la;
    cin>>n;
    if (n<=2)
      cout<<n<<endl;
    else
    {
      for (i=1;i<=n;++i)
        cin>>a[i];
      sort(a+1,a+n+1);
      for (i=1;i<n;++i)
        for (j=i+1;j<=n;++j)
        {
             ch=a[j]-a[i];
             la=j;
             sum=2;
             for (k=j+1;k<=n;++k)
               if (a[k]-a[la]==ch)
               {
                   la=k;
                   ++sum;
               }
             if (sum>ans)  ans=sum;
        }
        cout<<ans<<endl;
    }
}

 

2081:

题目描述  Description

一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)的数列。

在这个问题中a是一个非负的整数,b是正整数。写一个程序来找出在双平方数集合(双平方数集合是所有能表示成p的平方 + q的平方的数的集合,其中p和q为非负整数)S中长度为n的等差数列。

 

思路:先算出双平方数集合,m^2的食府,去重。然后,穷举起点和差(即等差数列的第二项),一开始有穷举了后面所有的项,n^3算法,超时稳稳地;后来做了个bool数组,然后直接加差值,若不存在就break,若当前值大于最大值也break,n^2m的算法,稳过。

 

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct use{
    int a,b;
}ans[100001],an;
int shu[200000]={0};
bool us[200000]={false};
int my_comp(const use &x,const use &y)
{
    if (x.b<y.b) return 1;
    if (x.b==y.b&&x.a<y.a) return 1;
    return 0;
}
int main()
{
    int sum,n,m,i,j,k,tot=0,size,ansi=0,la,maxn=0;
    scanf("%d%d",&n,&m);
    for (i=0;i<=m;++i)
      for (j=i;j<=m;++j)
      {
           ++tot;
           shu[tot]=i*i+j*j;
           us[shu[tot]]=true;
           maxn=max(maxn,shu[tot]);
      }
    sort(shu+1,shu+tot+1);
    size=unique(shu+1,shu+tot+1)-shu-1;
    tot=size;
    ansi=1;
    for (i=1;i<tot;++i)
      for (j=i+1;j<=tot;++j)
      {
          an.a=shu[i];
          an.b=shu[j]-shu[i];
          la=shu[j];
          sum=2;
          while (sum<n)
          {
              if (la>=maxn) break;
              if (!us[la+an.b]) break;
              la=la+an.b;
              ++sum;
          }
          if (sum==n)
          {
              ans[ansi].a=an.a;
              ans[ansi].b=an.b;
              ++ansi;
          }
      }
    --ansi;
    if (ansi==0) printf("NONE\n");
    else
    {
      sort(ans+1,ans+ansi+1,my_comp);
      for (i=1;i<=ansi;++i)
        printf("%d %d\n",ans[i].a,ans[i].b);
    }
}

 

2205:

题目描述  Description

等差数列的定义是一个数列S,它满足了(S[i]-S[i-1]) = d (i>1)。显然的一个单独的数字或者两个数字也可以形成一个等差数列。
经过一定的学习小C发现这个问题太简单了,等差数列的和不就是(Sn+S1)*n/2?因为这个问题实在是太简单了,小C不屑于去解决它。这让小C的老师愤怒了,他就找了另外一个问题来问他。
小C的老师给了他一个长度为N的数字序列,每个位置有一个整数,他需要小C帮他找到这个数字序列里面有多少个等差数列。
……
这个问题似乎太难了,小C需要你的程序帮他来解决这个问题。

 

思路:f[i][j]表示以i为终点(且i不为起点),差为j的个数,穷举起点和第二项,然后更新第二项的值。最后就需要加上n,以为一个元素也是等差数列。

 

code:

#include<iostream>
#include<cstdio>
using namespace std;
long long f[1001][5000]={0},a[1001]={0};
int main()
{
    int n,i,j,cha;
    long long ans=0;
    scanf("%d",&n);
    for (i=1;i<=n;++i)
        scanf("%d",&a[i]);
    for (i=1;i<n;++i)
      for (j=i+1;j<=n;++j)
      {
          cha=a[j]-a[i]+1000;
          f[j][cha]=(f[i][cha]+f[j][cha]+1)%9901;
      }
    ans=n;
    for (i=1;i<=n;++i)
      for (j=0;j<=2000;++j)
        ans=(ans+f[i][j])%9901;
    printf("%lld\n",ans);
}

 

 

 

你可能感兴趣的:(code)