Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Problem J:
SolveMe

$N$ 個の部屋があり, それぞれの部屋の床にはうさぎの絵が描かれている. あなたが部屋 $r$ のうさぎの絵の右耳の部分に乗ると, あなたは部屋 $A[r]$ に書かれたうさぎのしっぽの上にテレポートする. 同様に, 部屋 $r$ のうさぎの絵の左耳の部分に乗ると, 部屋 $B[r]$ に書かれたうさぎのしっぽの上にテレポートする.

整数 $X$, $Y$, $Z$ が与えられる. ねこは, 以下の条件を満たすようにテレポートを設定しようとしている. テレポートの $N^{2N}$ 通りの設定方法のうち, 条件を満たすものは何通りか, mod 1,000,000,007で求めよ.

条件: 任意の部屋 $r$ に対し, $r$ から右耳にちょうど $X$ 回乗り, 左耳にちょうど 1 回乗り, 右耳にちょうど $Y$ 回乗り, 左耳にちょうど 1 回乗り, 右耳にちょうど $Z$ 回乗ると, $r$ に戻る.

Constraints

$N$ will be between 1 and 1,000, inclusive.

$X$, $Y$, $Z$ will be between 0 and 1,000,000,000,000,000,000, inclusive.

Input

入力は以下の形式で与えられる:

$N$ $X$ $Y$ $Z$

Output

テレポートの設定方法を 1,000,000,007 で割ったあまりを表す整数を 1 行に出力せよ.

Sample Input 1

3 1 0 1

Sample Output 1

18

Sample Input 2

5 8 5 8

Sample Output 2

120

Solution in C++ (judge verdict: Accepted)

#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include <utility>
#include <queue>
#include <set>
#include <map>

using namespace std;
typedef  long long ll;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<VI> VVI;
#define  MP make_pair
#define  PB push_back
#define inf  1000000007
#define rep(i,n) for(int i=0;i<(int)(n);++i)

ll mod = 1000000007;
ll p[1001];
ll q[1001];
ll r[1001];

long long calc(long long  k,long long m){
	if(m==0)return 1;
	if(m==1)return k%mod;
	long long s = calc(k,m/2);
	if(m%2==0){
		return (s*s)%mod;
	}else{
		long long ans;
		ans = (s*s)%mod;
		return (k*ans)%mod;
	}
}


ll gcd(ll v,ll b){
	if(v>b) return gcd(b,v);
	if(v==b) return b;
	if(b%v==0) return v;
	return gcd(v,b%v);
}

int main(){
	p[0] = 1;
	q[0] = 1;
	r[0] = 1;
	r[1] = 1;
	for(ll i=2;i<=1000;i++){
		r[i] = r[i-2]*i%mod;
	}
	for(ll i=1;i<=1000;i++){
		p[i] = p[i-1]*i%mod;
	}
	for(ll i=1;i<=1000;i++){
		q[i] = calc(p[i],mod-2);
	}

	int n;
	ll x,y,w;
	cin >> n >> x >> y >> w;
	if(x==0&&y==0&&w==0){
		ll dp[1010][1010]={};
		dp[0][0] = 1;
		for(int i=1;i<=n;i++){
			for(ll j=0;j<=n;j++){
				if(dp[i-1][j]!=0){					
					dp[i][j] = (dp[i][j]+dp[i-1][j])%mod;
					dp[i][j+1] = (dp[i][j+1]+dp[i-1][j])%mod;
					if(j!=0){
						dp[i][j-1] = (dp[i][j-1]+j*dp[i-1][j])%mod;
					}
				}
			}
		}
		ll tmp = 1;
		for(int i=0;i<n;i++){
			tmp = (tmp*n)%mod;
		}
		cout << (dp[n][0]*tmp)%mod << endl;
	}else{
		ll k = x-y+w;
		if(k<0) k = -k;
		vector<int> a,b;
		if(k==0){
			for(int i=1;i<=n;i++){
				a.PB(i);
			}
		}else{
			for(int i=1;i<=n;i++){
				if(k%i==0){
					a.PB(i);
				}else{
					b.PB(i);
				}
			}
		}
		ll dp[1001][1001]={};
		for(int i=1;i<=n;i++){
			dp[i][0] = 1;
		}
		set<ll> st;
		for(ll i=1;i<=n;i++){
			ll g = i/gcd(i,k);
			st.insert(g);
			for(ll j=g*(n/g)-i;j>=0;j-=g){
				if(dp[g][j]!=0){
					for(ll s=j+i;s<=n;s+=i){
						ll tmp=1;
						tmp = (tmp * calc(calc(i,(s-j)/i),mod-2))%mod;
						tmp = (tmp * q[(s-j)/i])%mod;
						dp[g][s] = (dp[g][s] + dp[g][j] * tmp)%mod;
					}
				}
			}
		}
		// for(int i=1;i<=n;i++){
		// 	for(int j=1;j<=n;j++){
		// 		cout << calc(dp[i][j],mod-2) << " ";
		// 	}
		// 	cout << endl;
		// }
		ll dp2[1001][1001]={};
		for(int i=1;i<=n;i++){
			dp2[i][0] = 1;
		}
		for(ll i=1;i<=n;i++){
			if(st.count(i)==0)continue;
			if(i%2==0){
				for(ll j=2;j<=n/i;j+=2){
					dp2[i][j] = (calc(i,j/2) * r[j-1]) %mod;
				}
			}else{
				dp2[i][1] = 1;
				for(ll j=2;j<=n/i;j++){
					ll tmp = (dp2[i][j-2] * (j-1))%mod;
					tmp = (tmp * i)%mod;
					dp2[i][j] = (dp2[i][j]+tmp)%mod;
					dp2[i][j] = (dp2[i][j]+dp2[i][j-1])%mod;

				}
			}
		}

		ll dp3[1001]={};
		dp3[0] = 1;
		// for(int i=1;i<=n;i++){
		// 	for(int j=1;j<=n;j++){
		// 		cout << dp2[i][j] << " ";
		// 	}
		// 	cout << endl;
		// }
		for(int i=1;i<=n;i++){
			if(st.count(i)==0)continue;
			for(int j=n-i;j>=0;j--){
				if(dp3[j]!=0){
					for(int s = j+i;s<=n;s+=i){
						ll tmp = (dp3[j]*dp[i][s-j])%mod;
						dp3[s] = (dp3[s]+ tmp*dp2[i][(s-j)/i])%mod;
					}
				}
			}
			// for(int j=1;j<=n;j++){
			// 	cout << (dp3[j]*p[j])%mod << " " ;
			// }
			// cout << endl;
		}
		// for(int i=0;i<=n;i++){
		// 	cout << (dp3[i]*p[i])%mod << endl;
		// }

		cout << (dp3[n]*p[n])%mod << endl;
	}
	return 0;
}