很好的一道贪心+搜索题
首先,要明确大致上升的子序列的个数为( n-1 )*( n-1 )+1
明确了这个数量级之后,很容易想到对每一个最终序列枚举用到的步骤来进行搜索
搜索的时候要明确一个贪心的性质:对于每一个原始序列,最终形成的终止序列是唯一的,所以,对于不同的两个终止序列进行搜索的结果不会有重合。又因为不会有两个不同的起始序列通过相同的步骤之后会形成相同的终止序列,所以以上搜索不需要判重。复杂度 O( n*n+2^k )
启发:贪心的性质正着想不通可以倒着想。
#include<bits/stdc++.h>
using namespace std;
typedef int lint;
typedef long long LL;
typedef pair<lint,lint> pii;
vector<pii> op;
vector<string> ve;
lint ans;
void init(){
op.clear();
ve.clear();
ans = 0;
}
void getsort( lint n ){
string str;
for( lint i = 1;i <= n;i++ ){
str += '0' + i;
}
ve.push_back(str);
for( lint i = 1;i <= n;i++ ){
for( lint j = 1;j <= n;j++ ){
if( j == i || j == i-1 ) continue;
string cur = str;
if( i > j ) {
for (lint k = i; k > j; k--) {
swap(cur[k - 1], cur[k - 2]);
}
}else{
for( lint k = i; k < j;k++ ){
swap( cur[k-1],cur[k] );
}
}
ve.push_back( cur );
}
}
}
void dfs( lint numop,string& str ){
if( numop == op.size() ) {
ans++;
return;
}
lint l = op[ numop ].first - 1;
lint r = op[numop].second - 1;
if( str[l] > str[r] ) return;
swap( str[l],str[r] );
dfs( numop+1,str );
swap( str[l],str[r] );
dfs( numop+1,str );
}
int main(){
lint T,n,k,q;
scanf("%d",&T);
while( T-- ){
init();
scanf("%d%d%d",&n,&k,&q);
getsort(n);
for( lint l,r, i = 1;i <= k;i++ ){
scanf("%d%d",&l,&r);
op.push_back( pii( l,r ) );
}
reverse( op.begin(),op.end() );
for( lint i = 0;i < ve.size();i++ ){
dfs( 0,ve[i] );
}
cout << ans%q << endl;
}
return 0;
}