結果
| 問題 |
No.916 Encounter On A Tree
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2019-11-17 19:41:47 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 14 ms / 2,000 ms |
| コード長 | 4,345 bytes |
| コンパイル時間 | 1,909 ms |
| コンパイル使用メモリ | 171,748 KB |
| 実行使用メモリ | 11,520 KB |
| 最終ジャッジ日時 | 2024-09-25 06:04:19 |
| 合計ジャッジ時間 | 4,372 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 56 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1000000007;
template<long long mod> class ModInt {
public:
long long x;
ModInt():x(0) {
// do nothing
}
ModInt(long long y) : x(y>=0?(y%mod): (mod - (-y)%mod)%mod) {
// do nothing
}
ModInt &operator+=(const ModInt &p) {
if((x += p.x) >= mod) x -= mod;
return *this;
}
ModInt &operator+=(const long long y) {
ModInt p(y);
if((x += p.x) >= mod) x -= mod;
return *this;
}
ModInt &operator+=(const int y) {
ModInt p(y);
if((x += p.x) >= mod) x -= mod;
return *this;
}
ModInt &operator-=(const ModInt &p) {
if((x += mod - p.x) >= mod) x -= mod;
return *this;
}
ModInt &operator-=(const long long y) {
ModInt p(y);
if((x += mod - p.x) >= mod) x -= mod;
return *this;
}
ModInt &operator-=(const int y) {
ModInt p(y);
if((x += mod - p.x) >= mod) x -= mod;
return *this;
}
ModInt &operator*=(const ModInt &p) {
x = (x * p.x % mod);
return *this;
}
ModInt &operator*=(const long long y) {
ModInt p(y);
x = (x * p.x % mod);
return *this;
}
ModInt &operator*=(const int y) {
ModInt p(y);
x = (x * p.x % mod);
return *this;
}
ModInt &operator/=(const ModInt &p) {
*this *= p.inv();
return *this;
}
ModInt &operator/=(const long long y) {
ModInt p(y);
*this *= p.inv();
return *this;
}
ModInt &operator/=(const int y) {
ModInt p(y);
*this *= p.inv();
return *this;
}
ModInt operator=(const int y) const {
ModInt p(y);
*this = p;
return *this;
}
ModInt operator=(const long long y) const {
ModInt p(y);
*this = p;
return *this;
}
ModInt operator-() const { return ModInt(-x); }
ModInt operator++() {
x++;
if(x>=mod) x-=mod;
return *this;
}
ModInt operator--() {
x--;
if(x<0) x+=mod;
return *this;
}
ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
bool operator==(const ModInt &p) const { return x == p.x; }
bool operator!=(const ModInt &p) const { return x != p.x; }
ModInt inv() const {
int a = x, b = mod, u = 1, v = 0, t;
while(b > 0) {
t = a / b;
swap(a -= t * b, b);
swap(u -= t * v, v);
}
return ModInt(u);
}
ModInt pow(long long n) const {
ModInt ret(1), mul(x);
while(n > 0) {
if(n & 1) ret *= mul;
mul *= mul;
n >>= 1;
}
return ret;
}
friend ostream &operator<<(ostream &os, const ModInt &p) {
return os << p.x;
}
friend istream &operator>>(istream &is, ModInt &a) {
long long t;
is >> t;
a = ModInt<mod>(t);
return (is);
}
};
using modint = ModInt<MOD>;
int main() {
int d, l, r, k;
int MAX_d = 20;
cin >> d >> l >> r >> k;
vector<modint> fac((1<<MAX_d) + 1,1);
vector<int> pow2(MAX_d + 1, 1),sum(MAX_d + 1, 0);
//2冪を前計算
for (int i = 2; i < MAX_d + 1; ++i) pow2[i] = pow2[i - 1] * 2;
//2冪の和を前計算
for (int i = 1; i < MAX_d + 1; ++i) sum[i] = sum[i - 1] + pow2[i];
//階乗を前計算
for (long long i = 1; i < (1 << MAX_d) + 1; ++i) fac[i] = fac[i-1] * i;
//l,rを深さに変換
l = lower_bound(sum.begin(), sum.end(), l) - sum.begin();
r = lower_bound(sum.begin(), sum.end(), r) - sum.begin();
int lca = -1;
//lcaが存在するならそのlcaの深さを計算
if ((l + r - k) > 1 && (l + r - k) % 2 == 0) lca = (l + r - k) / 2;
//lcaが条件を満たしていない場合コーナー
if(lca == -1 || lca > l || lca > r){
cout << 0 << endl;
return 0;
}
modint ans = 1;
//上の段からl,r以外の頂点の順列の数え上げ
for (int i = 1; i <= d; ++i) {
int cnt = pow2[i];
if (i == l) cnt--;
if (i == r) cnt--;
ans *= fac[cnt];
}
//lcaとなるような頂点の位置についての数え上げ
ans *= pow2[lca];
//lcaを決め打ちした時のlの位置についての数え上げ
ans *= pow2[l - lca];
//lcaを決め打ちした時のrの位置についての数え上げ
ans *= pow2[r - lca];
//lcaについて、子は左右について2通りのパターンがあるため
ans *= 2;
cout << ans << endl;
return 0;
}