题意
给定一个
0
0
0 到
n
−
1
n-1
n−1 的全排列,问一共有多少
0
0
0 到
n
−
1
n-1
n−1 的全排列和该排列相似?
答案对 1e9+7 取模。
相似定义:如果两个全排列满足下面条件,就说两个这两个全排列相似。
对于一堆数 c 1 , c 2 , … , c k c_1,c_2,\ldots,c_k c1,c2,…,ck 的 MEX \operatorname{MEX} MEX 是指,在集合 c c c 中第一个未出现的非负整数 x x x。
思路
从 0 到 n-1,一个数一个数的判断,看其能放在哪些位置。所有可能的位置数相乘就是答案。
标记数 x 在原排列中所在位置为 p[x]。
p[0]。设 l 为较左端位置,r 为较右端位置。p[2] 位于 [l, r] 中,那么 2 可以放在 [l, r] 中的所有空闲位置;[l, r] 中,那么
MEX
[
l
,
r
]
\operatorname{MEX}[l, r]
MEX[l,r] 就达到 3 了,所以在相似排列中 2 只能放在 [l, r] 中)p[2];然后 p[2] 将 l 或者 r 更新;[l, r] 之外,那么
MEX
[
l
,
r
]
\operatorname{MEX}[l, r]
MEX[l,r] 只能达到 2,2不能在 [l, r] 中;而其位置如果改变的话,会有区间的 MEX 值改变,所以这种情况下 2 的位置不能改变)p[3] 位于 [l, r] 中,那么 3 可以放在 [l, r] 中的所有空闲位置;p[3];然后 p[3] 将 l 或者 r 更新;Code
#include<bits/stdc++.h>
using namespace std;
#define Ios ios::sync_with_stdio(false),cin.tie(0)
const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N], p[N];
signed main(){
Ios;
cin >> T;
while(T--)
{
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i], p[a[i]] = i;
int ans = 1;
int l = min(p[0], p[1]), r = max(p[0], p[1]);
for(int i=2;i<n;i++)
{
if(p[i] > l && p[i] < r)
{
ans = ans * (r-l+1 - i) % mod;
}
else{
if(p[i] < l) l = p[i];
else r = p[i];
}
}
cout << ans << endl;
}
return 0;
}
经验
当没有思路的时候应该沉下心来从最初始的情况一点一点往后推,也许推着推着就有思路了。
而不是看着样例胡乱想。。
题意
构造一个 n*m 的 01 矩阵,使得:
2 ≤ n , m ≤ 50 2 \le n,m \le 50 2≤n,m≤50 且都为偶数。
思路
这样构造:
6 8
1 0 0 1 1 0 0 1
0 1 1 0 0 1 1 0
0 1 1 0 0 1 1 0
1 0 0 1 1 0 0 1
1 0 0 1 1 0 0 1
0 1 1 0 0 1 1 0
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 210, mod = 1e9+7;
int T, n, m;
int a[N] = {1, 0, 0, 1}, b[N] = {0, 1, 1, 0};
int ans[N][N];
signed main(){
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
for(int i=1;i<=n;i++)
{
for(int j=0;j<m;j++)
{
if(i%4 == 1 || i%4 == 0) ans[i][j] = a[j%4];
else ans[i][j] = b[j%4];
}
}
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
printf("%d ", ans[i][j]);
}
printf("\n");
}
}
return 0;
}
题意
给定一个数
n
n
n,找到三个数
a
,
b
,
c
a, b, c
a,b,c 满足:
找不到输出 − 1 -1 −1。
1 ≤ n ≤ 1 0 9 , 0 ≤ a , b , c ≤ 1 0 9 1 \le n \le 10^9,\ 0 \le a, b, c \le 10^9 1≤n≤109, 0≤a,b,c≤109
思路
由
a
+
b
=
a
⊕
b
+
2
⋅
(
a
a + b = a \oplus b + 2 \cdot (a
a+b=a⊕b+2⋅(a &
b
)
b)
b) 可知,
a
⊕
b
a \oplus b
a⊕b 和
a
+
b
a + b
a+b 具有相同的奇偶性。
那么
n
=
(
a
⊕
b
)
+
(
b
⊕
c
)
+
(
a
⊕
c
)
n = (a\oplus b)+(b\oplus c)+(a\oplus c)
n=(a⊕b)+(b⊕c)+(a⊕c) 就和
(
a
+
b
)
+
(
b
+
c
)
+
(
a
+
c
)
=
2
⋅
(
a
+
b
+
c
)
(a+b) + (b+c) + (a+c) =2 \cdot (a+b+c)
(a+b)+(b+c)+(a+c)=2⋅(a+b+c) 具有相同奇偶性,一定为偶数。
Code
#include<bits/stdc++.h>
using namespace std;
#define Ios ios::sync_with_stdio(false),cin.tie(0)
const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N];
signed main(){
Ios;
cin >> T;
while(T--)
{
cin >> n;
if(n % 2 == 0) cout << n/2 << " " << 0 << " " << 0 << endl;
else cout << -1 << endl;
}
return 0;
}
经验
着重考虑特殊情况。