CodeForces - 1330B Dreamoon Likes Permutations(思维:最大数=全排列长度)

题目链接:https://vjudge.net/contest/366677#problem/B
CodeForces - 1330B Dreamoon Likes Permutations(思维:最大数=全排列长度)_第1张图片
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)。(最大的数值为全排列的长度

这里有两种情况:

  1. len1=ma,len2=n−ma
  2. len1=n−ma,len2=ma

代码

#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;
}

你可能感兴趣的:(思维数学)