1.合唱队型:把队伍分成两节,第一节找最长递增子序列,第二节找最长递减子序列,从而找到总的最长队形,即可知道要踢去几人
2.集合:新鲜的排序,将两个递增序列排在一起,找到两个序列中较小的数排在起来,代码虽短,但是技巧性很强。
#include<stdio.h>
int main()
{
int i,j,k,n,x[101],y[101],t,temp;
while(scanf("%d",&n)==1)
{
t=0;
for(i=0;i<n;i++)
scanf("%d",&x[i]);
for(i=0;i<n;i++) //以任意位置分开队伍
{
temp=0;
for(j=0;j<101;j++)
y[j]=240;
y[0]=y[n]=-1;
for(j=0;j<i;j++)
{
k=0;
while(x[j]>y[k])
{
if(x[j]>y[k]&&x[j]<y[k+1])y[k+1]=x[j];
k++;
}
}
for(j=i;j>0;j--)if(x[i]>y[j]){temp=j;break;} //找到递增子序列
for(j=n-1;j>i;j--)
{
k=n;
while(x[j]>y[k])
{
if(x[j]>y[k]&&x[j]<y[k-1])y[k-1]=x[j];
k--;
}
}
for(j=i+1;j<n;j++)if(x[i]>y[j]){temp+=n-j;break;} //找到递减子序列
if(t<temp)t=temp;
}
printf("%d\n",n-t-1);
}
return 0;
}
2.集合:新鲜的排序,将两个递增序列排在一起,找到两个序列中较小的数排在起来,代码虽短,但是技巧性很强。
#include<stdio.h>
int main()
{
int n,i,j=1,k=1,x[200000]={0,1},m;
for(i=2;i<=200000;i++)
{
m=2*x[j]+1;
n=4*x[k]+5;
if(m>n){x[i]=n;k++;}else{x[i]=m;j++;} //选择较小的那个排在当前数组后面
}
while(scanf("%d",&n)==1)
printf("%d\n",x[n]);
return 0;
}
3.Vigenère密码:和上次解密那题相似,找到解密的规律对密文进行操作。明文=密文-密匙+‘A'(或者'a')
#include<stdio.h>
#include<string.h>
int main()
{
int i,j,t,k;
char m[1005],c[105];
while(scanf("%s%s",c,m)==2)
{
t=strlen(c);
for(i=0;i<t;i++)
if(c[i]<='Z')c[i]-='A';else c[i]-='a'; //把密匙改成ascII码,方便操作
for(i=0,j=0;i<strlen(m);i++)
{
k=m[i]-c[j++];
if(m[i]>='a')if(k>='a')printf("%c",k);else printf("%c",k+26); //解密操作,j来记录是否重用密匙
else if(k>='A')printf("%c",k);else printf("%c",k+26);
if(j==t)j=0;
}
printf("\n");
}
return 0;
}