結果

問題 No.1001 注文の多い順列
ユーザー LayCurse
提出日時 2020-02-28 23:06:34
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 81 ms / 2,000 ms
コード長 11,278 bytes
コンパイル時間 3,147 ms
コンパイル使用メモリ 212,940 KB
最終ジャッジ日時 2025-01-09 03:11:35
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 31
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define MD (1000000007U)
void *wmem;
char memarr[96000000];
template<class T> inline void walloc1d(T **arr, int x, void **mem = &wmem){
static int skip[16] = {0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
(*mem) = (void*)( ((char*)(*mem)) + skip[((unsigned long long)(*mem)) & 15] );
(*arr)=(T*)(*mem);
(*mem)=((*arr)+x);
}
struct Modint{
unsigned val;
Modint(){
val=0;
}
Modint(int a){
val = ord(a);
}
Modint(unsigned a){
val = ord(a);
}
Modint(long long a){
val = ord(a);
}
Modint(unsigned long long a){
val = ord(a);
}
inline unsigned ord(unsigned a){
return a%MD;
}
inline unsigned ord(int a){
a %= (int)MD;
if(a < 0){
a += MD;
}
return a;
}
inline unsigned ord(unsigned long long a){
return a%MD;
}
inline unsigned ord(long long a){
a %= (int)MD;
if(a < 0){
a += MD;
}
return a;
}
inline unsigned get(){
return val;
}
inline Modint &operator+=(Modint a){
val += a.val;
if(val >= MD){
val -= MD;
}
return *this;
}
inline Modint &operator-=(Modint a){
if(val < a.val){
val = val + MD - a.val;
}
else{
val -= a.val;
}
return *this;
}
inline Modint &operator*=(Modint a){
val = ((unsigned long long)val*a.val)%MD;
return *this;
}
inline Modint &operator/=(Modint a){
return *this *= a.inverse();
}
inline Modint operator+(Modint a){
return Modint(*this)+=a;
}
inline Modint operator-(Modint a){
return Modint(*this)-=a;
}
inline Modint operator*(Modint a){
return Modint(*this)*=a;
}
inline Modint operator/(Modint a){
return Modint(*this)/=a;
}
inline Modint operator+(int a){
return Modint(*this)+=Modint(a);
}
inline Modint operator-(int a){
return Modint(*this)-=Modint(a);
}
inline Modint operator*(int a){
return Modint(*this)*=Modint(a);
}
inline Modint operator/(int a){
return Modint(*this)/=Modint(a);
}
inline Modint operator+(long long a){
return Modint(*this)+=Modint(a);
}
inline Modint operator-(long long a){
return Modint(*this)-=Modint(a);
}
inline Modint operator*(long long a){
return Modint(*this)*=Modint(a);
}
inline Modint operator/(long long a){
return Modint(*this)/=Modint(a);
}
inline Modint operator-(void){
Modint res;
if(val){
res.val=MD-val;
}
else{
res.val=0;
}
return res;
}
inline operator bool(void){
return val!=0;
}
inline operator int(void){
return get();
}
inline operator long long(void){
return get();
}
inline Modint inverse(){
int a = val;
int b = MD;
int u = 1;
int v = 0;
int t;
Modint res;
while(b){
t = a / b;
a -= t * b;
swap(a, b);
u -= t * v;
swap(u, v);
}
if(u < 0){
u += MD;
}
res.val = u;
return res;
}
inline Modint pw(unsigned long long b){
Modint a(*this);
Modint res;
res.val = 1;
while(b){
if(b&1){
res *= a;
}
b >>= 1;
a *= a;
}
return res;
}
inline bool operator==(int a){
return ord(a)==val;
}
inline bool operator!=(int a){
return ord(a)!=val;
}
}
;
inline Modint operator+(int a, Modint b){
return Modint(a)+=b;
}
inline Modint operator-(int a, Modint b){
return Modint(a)-=b;
}
inline Modint operator*(int a, Modint b){
return Modint(a)*=b;
}
inline Modint operator/(int a, Modint b){
return Modint(a)/=b;
}
inline Modint operator+(long long a, Modint b){
return Modint(a)+=b;
}
inline Modint operator-(long long a, Modint b){
return Modint(a)-=b;
}
inline Modint operator*(long long a, Modint b){
return Modint(a)*=b;
}
inline Modint operator/(long long a, Modint b){
return Modint(a)/=b;
}
inline void rd(int &x){
int k;
int m=0;
x=0;
for(;;){
k = getchar_unlocked();
if(k=='-'){
m=1;
break;
}
if('0'<=k&&k<='9'){
x=k-'0';
break;
}
}
for(;;){
k = getchar_unlocked();
if(k<'0'||k>'9'){
break;
}
x=x*10+k-'0';
}
if(m){
x=-x;
}
}
inline void wt_L(char a){
putchar_unlocked(a);
}
inline void wt_L(int x){
int s=0;
int m=0;
char f[10];
if(x<0){
m=1;
x=-x;
}
while(x){
f[s++]=x%10;
x/=10;
}
if(!s){
f[s++]=0;
}
if(m){
putchar_unlocked('-');
}
while(s--){
putchar_unlocked(f[s]+'0');
}
}
inline void wt_L(unsigned x){
int s=0;
char f[10];
while(x){
f[s++]=x%10;
x/=10;
}
if(!s){
f[s++]=0;
}
while(s--){
putchar_unlocked(f[s]+'0');
}
}
inline void wt_L(long long x){
int s=0;
int m=0;
char f[20];
if(x<0){
m=1;
x=-x;
}
while(x){
f[s++]=x%10;
x/=10;
}
if(!s){
f[s++]=0;
}
if(m){
putchar_unlocked('-');
}
while(s--){
putchar_unlocked(f[s]+'0');
}
}
inline void wt_L(unsigned long long x){
int s=0;
char f[21];
while(x){
f[s++]=x%10;
x/=10;
}
if(!s){
f[s++]=0;
}
while(s--){
putchar_unlocked(f[s]+'0');
}
}
inline void wt_L(Modint x){
int i;
i = (int)x;
wt_L(i);
}
inline void wt_L(double x){
printf("%.15f",x);
}
inline void wt_L(const char c[]){
int i=0;
for(i=0;c[i]!='\0';i++){
putchar_unlocked(c[i]);
}
}
inline void wt_L(string &x){
int i=0;
for(i=0;x[i]!='\0';i++){
putchar_unlocked(x[i]);
}
}
template<class S, class T> inline S chmax(S &a, T b){
if(a<b){
a=b;
}
return a;
}
template<class T> struct Comb{
int mem_fact;
T *factri;
T *ifactri;
Comb(){
mem_fact = 0;
}
inline void expand_fact(int k){
if(k <= mem_fact){
return;
}
chmax(k, 2* mem_fact);
if(mem_fact == 0){
int i;
factri = (T*)malloc(k * sizeof(T));
ifactri = (T*)malloc(k * sizeof(T));
factri[0] = 1;
for(i=(1);i<(k);i++){
factri[i] = i * factri[i-1];
}
ifactri[k-1] = 1 / factri[k-1];
for(i=(k-1)-1;i>=(0);i--){
ifactri[i] = (i+1) * ifactri[i+1];
}
}
else{
int i;
factri = (T*)realloc(factri, k * sizeof(T));
ifactri = (T*)realloc(ifactri, k * sizeof(T));
for(i=(mem_fact);i<(k);i++){
factri[i] = i * factri[i-1];
}
ifactri[k-1] = 1 / factri[k-1];
for(i=(k-1)-1;i>=(mem_fact);i--){
ifactri[i] = (i+1) * ifactri[i+1];
}
}
mem_fact = k;
}
inline T fac(int k){
if(mem_fact < k+1){
expand_fact(k+1);
}
return factri[k];
}
inline T ifac(int k){
if(mem_fact < k+1){
expand_fact(k+1);
}
return ifactri[k];
}
inline T C(int a, int b){
if(b < 0 || b > a){
return 0;
}
if(mem_fact < a+1){
expand_fact(a+1);
}
return factri[a] * ifactri[b] * ifactri[a-b];
}
inline T P(int a, int b){
if(b < 0 || b > a){
return 0;
}
if(mem_fact < a+1){
expand_fact(a+1);
}
return factri[a] * ifactri[a-b];
}
inline T H(int a, int b){
if(a==0 && b==0){
return 1;
}
if(a <= 0 || b < 0){
return 0;
}
if(mem_fact < a+b){
expand_fact(a+b);
}
return C(a+b-1, b);
}
inline T Multinomial(int sz, int a[]){
int i;
int s = 0;
T res;
for(i=(0);i<(sz);i++){
s += a[i];
}
if(mem_fact < s+1){
expand_fact(s+1);
}
res = factri[s];
for(i=(0);i<(sz);i++){
res *= ifactri[a[i]];
}
return 1;
}
inline T Multinomial(int a){
return 1;
}
inline T Multinomial(int a, int b){
if(mem_fact < a+b+1){
expand_fact(a+b+1);
}
return factri[a+b] * ifactri[a] * ifactri[b];
}
inline T Multinomial(int a, int b, int c){
if(mem_fact < a+b+c+1){
expand_fact(a+b+c+1);
}
return factri[a+b+c] * ifactri[a] * ifactri[b] * ifactri[c];
}
inline T Multinomial(int a, int b, int c, int d){
if(mem_fact < a+b+c+d+1){
expand_fact(a+b+c+d+1);
}
return factri[a+b+c+d] * ifactri[a] * ifactri[b] * ifactri[c] * ifactri[d];
}
inline T Catalan(int n){
if(n < 0){
return 0;
}
if(mem_fact < 2*n+1){
expand_fact(2*n+1);
}
return factri[2*n] * ifactri[n] * ifactri[n+1];
}
inline T C_s(long long a, long long b){
long long i;
T res;
if(b < 0 || b > a){
return 0;
}
if(b > a - b){
b = a - b;
}
res = 1;
for(i=(0);i<(b);i++){
res *= a - i;
res /= i + 1;
}
return res;
}
inline T P_s(long long a, long long b){
long long i;
T res;
if(b < 0 || b > a){
return 0;
}
res = 1;
for(i=(0);i<(b);i++){
res *= a - i;
}
return res;
}
inline T per_s(long long n, long long k){
T d;
int m;
if(n < 0 || k < 0){
return 0;
}
if(n == k && k == 0){
return 1;
}
if(n == 0 || k == 0){
return 0;
}
if(k==1){
return 1;
}
if(k==2){
d = n / 2;
return d;
}
if(k==3){
d = (n-1) / 6;
m = (n-1) % 6;
if(m==0){
return 3 * d * d + d;
}
if(m==1){
return 3 * d * d + 2 * d;
}
if(m==2){
return 3 * d * d + 3 * d + 1;
}
if(m==3){
return 3 * d * d + 4 * d + 1;
}
if(m==4){
return 3 * d * d + 5 * d + 2;
}
if(m==5){
return 3 * d * d + 6 * d + 3;
}
}
assert(0 && "per_s should be k <= 3");
return -1;
}
}
;
int N;
int T;
int X;
int As;
int A[3000];
int ac[3001];
int Bs;
int B[3000];
int bc[3001];
Modint dp[3001][3001];
int vis[3001][3001];
Modint solve(int x, int y){
int k = x + y;
Modint res = 0;
if(vis[x][y]){
return dp[x][y];
}
vis[x][y] = 1;
if(k==N){
return dp[x][y] = 1;
}
if(x < As && ac[k] - (As-1-x) > 0){
res += solve(x+1, y) * (ac[k] - (As-1-x));
}
if(y < Bs && bc[k] - y > 0){
res += solve(x, y+1) * (bc[k] - y);
}
return dp[x][y] = res;
}
int main(){
int i;
wmem = memarr;
Modint res;
Comb<Modint> c;
rd(N);
for(i=(0);i<(N);i++){
rd(T);
rd(X);
if(T==0){
A[As++] = X;
}
if(T==1){
B[Bs++] = N-X+1;
}
}
for(i=(0);i<(As);i++){
int j;
for(j=(0);j<(A[i]);j++){
ac[j]++;
}
}
for(i=(0);i<(Bs);i++){
int j;
for(j=(0);j<(B[i]);j++){
bc[N-1-j]++;
}
}
wt_L(solve(0,0));
wt_L('\n');
return 0;
}
// cLay varsion 20200227-1
// --- original code ---
// int N, T, X;
// int As, A[3000], ac[3001];
// int Bs, B[3000], bc[3001];
// Modint dp[3001][3001];
// int vis[3001][3001];
//
// Modint solve(int x, int y){
// int k = x + y;
// Modint res = 0;
//
// if(vis[x][y]) return dp[x][y];
// vis[x][y] = 1;
// if(k==N) return dp[x][y] = 1;
//
// if(x < As && ac[k] - (As-1-x) > 0) res += solve(x+1, y) * (ac[k] - (As-1-x));
// if(y < Bs && bc[k] - y > 0) res += solve(x, y+1) * (bc[k] - y);
//
// return dp[x][y] = res;
// }
//
// {
// Modint res;
// Comb<Modint> c;
//
// rd(N);
// rep(i,N){
// rd(T,X);
// if(T==0) A[As++] = X;
// if(T==1) B[Bs++] = N-X+1;
// }
// rep(i,As) rep(j,A[i]) ac[j]++;
// rep(i,Bs) rep(j,B[i]) bc[N-1-j]++;
//
// wt(solve(0,0));
// }
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0