版权声明:本文为博主原创文章,欢迎转载。 https://blog.csdn.net/Smiler_/article/details/82108617
C. The Phone Number
题意:给你n个数字从1到n,现在让你用这n个数字构造一个序列,使得最长上升子序列和最长下降子序列的和最小。
思路:我们可以先打一个表观察一下规律,通过打标找规律我们可以发现,对于n<=x*y,当x+y最小的时候就是最小的和,通过分析我们可以发现,我们相当于是把n个数字分成x组,使得每组最多y个数字,在每一组中构成的是最长下降序列,x组构成的是最长上升子序列。打表我是把n的全排列构造出来,然后求每个全排列的最长上升子序列和最长下降子序列的和,把和最小的序列打印出来。
#include <algorithm>
#include <vector>
#include <cstdio>
#include <set>
#include <map>
#include <cstring>
#include <string>
#include <iostream>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
if(n==1)
{
cout<<1<<endl;;
return 0;
}
int minn=10000000;
int a,b;
for(int i=1; i<=n; i++)
{
int x=i;
int y=n/i;
if(x*y==n)
{
if(x+y<minn)
{
minn=x+y;
a=x;
b=y;
}
}
else
{
if(x+y+1<minn&&(x+1)*y>=n)
{
minn=x+y+1;
a=x+1;
b=y;
}
if(x+y+1<minn&&(x)*(y+1)>=n)
{
minn=x+y+1;
a=x;
b=y+1;
}
}
}
int f=0;
int t=0;
for(int i=1; i+b-1<=n; i+=b)
{
int x=i+b-1;
for(int j=x; j>=i; j--)
{
if(f==0)
{
cout<<j;
f=1;
}
else
{
cout<<" "<<j;
}
}
t=x;
}
for(int j=n; j>t; j--)
{
if(f==0)
{
cout<<j;
f=1;
}
else
cout<<" "<<j;
}
cout<<endl;
}