首页 > 代码库 > CODEVS1006&&2081&&2205等差数列
CODEVS1006&&2081&&2205等差数列
复习dp,做了一系列的等差数列,突然发现第一个和第二个是穷举的。。。
1006:
给定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:
一个等差数列是一个能表示成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:
等差数列的定义是一个数列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);
}
CODEVS1006&&2081&&2205等差数列