A,先把各个区间翻转映射为一段序列----可以发现,通过这段序列转化与原问题等价
那么可以套用快速mi的思想。。。。
直接做就好了
考场上思路假了,打表推式子推了一年。。。。。但还是没找出规律。。。。
套路见太少了
套路见太少了
#include<bits/stdc++.h>
#define MAXN 200005
typedef long long ll;
using namespace std;
int n,m,l[15],r[15],num2[MAXN],num[MAXN],num3[MAXN];
ll k;
void poww(ll k){
while(k){
if(k & 1){
for(int i = 1 ; i <= n ; i++){
num3[i] = num[num2[i]];
}
swap(num3 , num);
}
//}
for(int i = 1 ; i <= n ; i++)num3[i] = num2[num2[i]];
swap(num2 , num3);
k = k >> 1;
}
for(int i = 1 ; i <= n ; i++)cout<<num[i]<<" ";
}
int main(){
cin>>n>>m>>k;
for(int i = 1 ; i <= n ; i++)num[i] = num2[i] = i;
for(int i = 1 ; i <= m ; i++){
cin>>l[i]>>r[i];
}
for(int i = 1 ; i <= m ; i++){
for(int j = 1 ; j <= r[i] - l[i] + 1 ; j++){
if(j + l[i] - 1 >= r[i] - j + 1)break;
swap(num2[j + l[i] - 1] , num2[r[i] - j + 1]);
}
}
poww(k);
}
B,考虑补集转换,至少有一个喜欢的 = 总方案 - 没有一个喜欢的
考虑计算总方案
令
F
[
i
]
F[i]
F[i]为现在的数的总和为
i
i
i的方案数
则
F
[
i
]
=
s
i
g
a
m
a
(
f
[
i
−
k
]
[
1
<
=
k
<
i
]
)
+
1
F[i] = sigama(f[i - k][1 <= k < i]) + 1
F[i]=sigama(f[i−k][1<=k<i])+1
可得
F
[
i
]
=
2
i
−
1
F[i] = 2 ^ {i - 1}
F[i]=2i−1
那么考虑没有一个喜欢的:
令
G
[
i
]
G[i]
G[i]为现在的数总和为i,通过喜欢的来划分的方案数
G
[
i
]
=
s
i
g
a
m
(
G
[
i
−
t
[
k
]
]
)
G[i] = sigam(G[i - t[k]])
G[i]=sigam(G[i−t[k]])并不好计算
巨佬说直接套矩阵快速mi就好了
然而并不会。。。。。
C、在 [ 1 , n ] [1,n] [1,n]内选出m个数,并且选出的这m个数为单峰序列的方案数
trick:遇到递增问题:考虑转换为差分
考虑选出序列的差分数组
发现前半部分:
s
u
m
>
=
j
sum >= j
sum>=j
后半部分 :
s
u
m
<
j
sum < j
sum<j
直接转换为dp
然后推式子即可