题目链接:https://vjudge.net/contest/366677#problem/B
Input
6
5
1 4 3 2 1
6
2 4 1 3 2 1
4
2 1 1 3
4
1 3 3 1
12
2 1 3 4 5 6 7 8 9 1 10 2
3
1 1 1
Output
2
1 4
4 1
1
4 2
0
0
1
2 10
0
翻译:
输入n个数,求是否能把这个长度为n的数组分成两个全排列。
记录有多少次方法,和每次分成的两个全排列的长度。
例如:
5
1 4 3 2 1
有2种办法 {1}+{4,3,2,1}and {1,4,3,2}+{1}
分析:
全排列:如果m 个整数的序列包含了1~m的整数,且1到m正好出现一次。m这个数叫做全排列的长度。
令ma为数组中的最大值。
如果把数组a分成两个全排列p1和p2,那么ma一定是max(len1,len2)。(最大的数值为全排列的长度)
这里有两种情况:
代码:
#include
#include
#include
using namespace std;
const int N=2*1e5+10;
int n,a[N];
int mx;
int index[2][2],cnt;
void init()
{
mx=0;
cnt=0;
memset(index,0,sizeof(index));
}
bool solve(int a[],int n)
{
bool book[N];
for(int i=1; i<=n; i++)
book[i]=false;
for(int i=0; i<n; i++)
book[a[i]]=true;
for(int i=1; i<=n; i++)
{
if(!book[i])
return 0;
}
return 1;
}
bool judge(int len1,int n)
{
return solve(a,len1)&&solve(a+len1,n-len1);/*a a+len1分别为数组的起始位置,从这个位置开始遍历*/
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
mx=max(mx,a[i]);
}
if(judge(n-mx,n))
{
index[cnt][0]=n-mx;
index[cnt++][1]=mx;
}
if(mx*2!=n&&judge(mx,n))/*mx*2和n比较,排除两个全排列的长度相等的情况*/
{
index[cnt][0]=mx;
index[cnt++][1]=n-mx;
}
printf("%d\n",cnt);
for(int i=0; i<cnt; i++)
printf("%d %d\n",index[i][0],index[i][1]);
}
return 0;
}