提出 #45351007
ソースコード 拡げる
#include <iostream> // cout, endl, cin
#include <string> // string, to_string, stoi
#include <vector> // vector
#include <algorithm> // min, max, swap, sort, reverse, lower_bound, upper_bound
#include <utility> // pair, make_pair
#include <tuple> // tuple, make_tuple
#include <cstdint> // int64_t, int*_t
#include <cstdio> // printf
#include <map> // map
#include <queue> // queue, priority_queue
#include <set> // set
#include <stack> // stack
#include <deque> // deque
#include <unordered_map> // unordered_map
#include <unordered_set> // unordered_set
#include <bitset> // bitset
#include <cctype> // isupper, islower, isdigit, toupper, tolower
#include <iomanip>
#include <climits>
#include <cmath>
#include <functional>
#include <numeric>
#include <regex>
#include <array>
#include <fstream>
#include <sstream>
//#include<atcoder/modint>
//using namespace atcoder;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep1(i, n) for (int i = 1; i <= (int)(n); i++)
#define repl(i,l,r) for (int i = l; i < (int)(r); i++)
#define all(a) a.begin(),a.end()
#define Pii pair<int,int>
#define Pll pair<long,long>
#define INFi 1000000001
#define INFl 1000000000000000001
#define ll long long
using namespace std;
template<class T> inline bool chmin(T& a, T b) {
if (a > b) {
a = b;
return true;
}
return false;
}
template<class T> inline bool chmax(T& a, T b) {
if (a < b) {
a = b;
return true;
}
return false;
}
template<class T> void printArray(vector<T>&A){
for(T&a:A){
cout<<a<<" ";
}
cout<<endl;
}
template<class T> void printArrayln(vector<T>&A){
for(T&a:A){
cout<<a<<endl;
}
}
template<class T1,class T2> std::ostream &operator<<(std::ostream &out, const pair<T1,T2> &A){
cout<<"{"<<A.first<<","<<A.second<<"}";
return out;
}
template<class T1,class T2> std::ostream &operator<<(std::ostream &out, const map<T1,T2> &M){
for(const auto&A:M){
cout<<"{"<<A.first<<","<<A.second<<"}";
}
return out;
}
template<class T1> std::ostream &operator<<(std::ostream &out, const set<T1> &M){
cout<<"{";
for(const auto&A:M){
cout<<A<<", ";
}
cout<<"}"<<endl;
return out;
}
template<class T1> std::ostream &operator<<(std::ostream &out, const multiset<T1> &M){
cout<<"{";
for(const auto&A:M){
cout<<A<<", ";
}
cout<<"}"<<endl;
return out;
}
template<class T> std::ostream &operator<<(std::ostream &out, const vector<T> &A){
for(const T &a:A){
cout<<a<<" ";
}
return out;
}
void print() { cout << endl; }
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
cout << H << " ";
print(T...);
}
template<class T> std::istream &operator>>(std::istream &in,vector<T>&A){
for(T&a:A){
std::cin>>a;
}
return in;
}
// modint: mod 計算を int を扱うように扱える構造体
template<int MOD> struct Fp {
long long val;
constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
if (val < 0) val += MOD;
}
constexpr int getmod() { return MOD; }
constexpr Fp operator - () const noexcept {
return val ? MOD - val : 0;
}
constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
constexpr Fp& operator += (const Fp& r) noexcept {
val += r.val;
if (val >= MOD) val -= MOD;
return *this;
}
constexpr Fp& operator -= (const Fp& r) noexcept {
val -= r.val;
if (val < 0) val += MOD;
return *this;
}
constexpr Fp& operator *= (const Fp& r) noexcept {
val = val * r.val % MOD;
return *this;
}
constexpr Fp& operator /= (const Fp& r) noexcept {
long long a = r.val, b = MOD, u = 1, v = 0;
while (b) {
long long t = a / b;
a -= t * b; swap(a, b);
u -= t * v; swap(u, v);
}
val = val * u % MOD;
if (val < 0) val += MOD;
return *this;
}
constexpr bool operator == (const Fp& r) const noexcept {
return this->val == r.val;
}
constexpr bool operator != (const Fp& r) const noexcept {
return this->val != r.val;
}
friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
return os << x.val;
}
friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
if (n == 0) return 1;
auto t = modpow(a, n / 2);
t = t * t;
if (n & 1) t = t * a;
return t;
}
};
using mint = Fp<1000000007>;
mint dp[3001][3001][2][2];
vector<mint> f(int n){
if(n==1){
return vector<mint>{mint(1), mint(1)};
}
rep(i,3001)rep(j,3001)rep(k,2)rep(l,2)dp[i][j][k][l] = mint(0);
// nはサイクルの長さ
// dp[i][j][k][l] :=
// i番目までの辺を見て、j個使ったとき、
// k=0: 直前を使っていない k=1: 直前を使った
// l=0: 0を使っていない l=1: 0を使った
dp[0][0][0][0] = 1;
for(int i=1;i<=n;i++){
for(int j=0;j<=n;j++){
if(i==1){
// 使わない
dp[i][j][0][0] += dp[i-1][j][0][0];
if(j>0){
// 前を使う
dp[i][j][0][1] += dp[i-1][j-1][0][0];
// 後ろを使う
dp[i][j][1][0] += dp[i-1][j-1][0][0];
}
}else if(i==n){
// 使わない
dp[i][j][0][0] += dp[i-1][j][0][0];
dp[i][j][0][0] += dp[i-1][j][1][0];
dp[i][j][0][1] += dp[i-1][j][0][1];
dp[i][j][0][1] += dp[i-1][j][1][1];
if(j>0){
// 前を使う
dp[i][j][0][0] += dp[i-1][j-1][0][0];
dp[i][j][0][1] += dp[i-1][j-1][0][1];
// 後ろを使う
dp[i][j][1][0] += dp[i-1][j-1][0][0];
dp[i][j][1][0] += dp[i-1][j-1][1][0];
}
}else{
rep(l,2){
// 使わない
dp[i][j][0][l] += dp[i-1][j][0][l];
dp[i][j][0][l] += dp[i-1][j][1][l];
if(j>0){
// 前を使う
dp[i][j][0][l] += dp[i-1][j-1][0][l];
// 後ろを使う
dp[i][j][1][l] += dp[i-1][j-1][0][l];
dp[i][j][1][l] += dp[i-1][j-1][1][l];
}
}
}
}
}
vector<mint> res(n+1, mint(0));
rep(j,n+1){
rep(k,2){
rep(l,2){
res[j] += dp[n][j][k][l];
}
}
}
return res;
}
int main(void){
std::cin.tie(0)->sync_with_stdio(0);
int N;cin>>N;
vector<int> p(N),q(N);
rep(i,N){cin>>p[i];p[i]--;}
rep(i,N){cin>>q[i];q[i]--;}
vector<vector<int>> G(N);
rep(i,N){
G[p[i]].push_back(q[i]);
G[q[i]].push_back(p[i]);
}
// サイクルを検出する
vector<int> len(0); //i番目の連結成分の長さ
vector<bool> used(N,false);
rep(i,N){
if(used[i])continue;
int now=i;
int cnt=0;
int prev=-1;
while(!used[now]){
used[now]=true;
cnt++;
for(int next:G[now]){
if(next==prev)continue;
prev=now;
now=next;
break;
}
}
len.push_back(cnt);
}
vector<mint> dp(N+1, mint(0));
// dp[i] := i個の頂点を使ったときの場合の数
dp[0] = 1;
rep(j,len.size()){
//cout<<len[j]<<" "<<g[j]<<endl;
vector<mint> g = f(len[j]);
for(int i=N;i>=0;i--){
for(int k=1;k<=len[j];k++){
if(i-k<0)break;
dp[i] += dp[i-k]*g[k];
}
}
}
vector<mint> fac(N+1, mint(0));
fac[0] = 1;
rep1(i,N){
fac[i] = fac[i-1]*mint(i);
}
mint ans = fac[N];
rep1(i,N){
if(i%2==0){
ans += dp[i]*fac[N-i];
}else{
ans -= dp[i]*fac[N-i];
}
}
cout<<ans<<endl;
}
提出情報
ジャッジ結果
| セット名 |
Sample |
All |
| 得点 / 配点 |
0 / 0 |
600 / 600 |
| 結果 |
|
|
| セット名 |
テストケース |
| Sample |
example_00.txt, example_01.txt, example_02.txt |
| All |
corner_00.txt, corner_01.txt, cycle_00.txt, cycle_01.txt, cycle_02.txt, cycle_03.txt, cycle_04.txt, cycle_05.txt, example_00.txt, example_01.txt, example_02.txt, rand_00.txt, rand_01.txt, rand_02.txt, rand_03.txt, rand_04.txt, rand_05.txt, rand_06.txt, rand_07.txt, rand_08.txt, rand_09.txt, rand_10.txt, rand_11.txt, rand_12.txt, rand_13.txt, rand_14.txt, rand_15.txt, rand_16.txt, rand_17.txt, rand_18.txt, rand_19.txt |
| ケース名 |
結果 |
実行時間 |
メモリ |
| corner_00.txt |
AC |
1 ms |
3516 KiB |
| corner_01.txt |
AC |
19 ms |
3676 KiB |
| cycle_00.txt |
AC |
164 ms |
285084 KiB |
| cycle_01.txt |
AC |
162 ms |
285068 KiB |
| cycle_02.txt |
AC |
114 ms |
285088 KiB |
| cycle_03.txt |
AC |
131 ms |
284996 KiB |
| cycle_04.txt |
AC |
117 ms |
285176 KiB |
| cycle_05.txt |
AC |
161 ms |
285140 KiB |
| example_00.txt |
AC |
120 ms |
284912 KiB |
| example_01.txt |
AC |
95 ms |
284948 KiB |
| example_02.txt |
AC |
146 ms |
284756 KiB |
| rand_00.txt |
AC |
311 ms |
285124 KiB |
| rand_01.txt |
AC |
328 ms |
285124 KiB |
| rand_02.txt |
AC |
289 ms |
285284 KiB |
| rand_03.txt |
AC |
364 ms |
285128 KiB |
| rand_04.txt |
AC |
264 ms |
284968 KiB |
| rand_05.txt |
AC |
291 ms |
285104 KiB |
| rand_06.txt |
AC |
308 ms |
284980 KiB |
| rand_07.txt |
AC |
231 ms |
284860 KiB |
| rand_08.txt |
AC |
222 ms |
285064 KiB |
| rand_09.txt |
AC |
122 ms |
284864 KiB |
| rand_10.txt |
AC |
257 ms |
284944 KiB |
| rand_11.txt |
AC |
250 ms |
284828 KiB |
| rand_12.txt |
AC |
171 ms |
284776 KiB |
| rand_13.txt |
AC |
208 ms |
285020 KiB |
| rand_14.txt |
AC |
278 ms |
285044 KiB |
| rand_15.txt |
AC |
225 ms |
284868 KiB |
| rand_16.txt |
AC |
302 ms |
285108 KiB |
| rand_17.txt |
AC |
311 ms |
285044 KiB |
| rand_18.txt |
AC |
138 ms |
284936 KiB |
| rand_19.txt |
AC |
211 ms |
284988 KiB |