提出 #50047211


ソースコード 拡げる

#include <bits/stdc++.h>
#include <atcoder/modint>
const int MOD=998244353;
using mint = atcoder::static_modint<MOD>;
using namespace std;
typedef long long ll;
#define rep(i,a,n) for (ll i=a;i<(ll)(n);i++)
#define per(i,a,n) for (ll i=n;i-->(ll)(a);)
ll read(){ll r;scanf("%lld",&r);return r;}

const int N=3000;
int a[N+10];
bool exist[N+10]; // v[i] = i出现过
int l[N+10]; // l[value] = 比l小的 未填的个数
int lp[N+10]; // lp[idx] = 比idx小的 未填位置的个数
mint fac[N+10]={1};
mint ifac[N+10];
mint inv[N+10];
mint binom(int n,int m){ return (m > n or m < 0)?0: fac[n]*ifac[m]*ifac[n-m]; }
mint sum(ll a,ll b) {
  if(a > b) return 0;
  assert(a<=b);
  return (a+b)*(b-a+1)/2;
}

int main(){
  rep(i,1,N+1) fac[i]=fac[i-1]*i;
  ifac[N]=fac[N].inv();
  per(i,0,N) ifac[i]=ifac[i+1]*(i+1);
  rep(i,1,N) inv[i] = ifac[i]*fac[i-1];
  int n=read();
  rep(i,1,n+1) a[i]=read();
  rep(i,1,n+1) if(a[i]!=-1) exist[a[i]]=1;
  ll x=0; // -1的个数
  rep(i,1,n+1) x+=a[i]==-1;
  // 计算比
  int cnt = 0;
  rep(v,1,n+1) {
    if(!exist[v]) cnt++;
    else l[v] = cnt;
  }
  cnt = 0;
  rep(i,1,n+1) {
    if(a[i] == -1) cnt++;
    else lp[i] = cnt;
  }
  mint ans = 0;
  // (l0,r0,l1,r1)
  // A 2个确定: A=逆序对个数
  mint A = 0;
  rep(i,1,n+1) if(a[i] != -1) rep(j,i+1,n+1) if(a[j] != -1 and a[j] < a[i]) A++;
  // B 1个确定:
  // C 0个确定:

  // (A,A)
  ans += A*A*fac[x];

  // (A,B),(B,A)
  rep(i,1,n+1) if(a[i] != -1) {
    // (p,i) A
    ans+=lp[i]*(x-l[a[i]])*fac[x-1]*A*2; // 左侧位置,更大值,剩余随便放, 对称x2
    // (i,p) A
    ans+=(x-lp[i])*l[a[i]]*fac[x-1]*A*2; // 右侧位置,更小值,剩余随便放, 对称x2
  }

  // (A,C),(C,A)
  ans += fac[x]*binom(x,2)*inv[2]*A*2; // 所有排列,选2个位置,1/2产出率,A的方案,对称

  // (C,C)
  //    (l0,r0) == (l1,r1)
  ans += fac[x]*binom(x,2)*inv[2]; // 所有排列,选2个位置,1/2产出率
  //    l0 == l1, or  r0 == r1
  ans += fac[x]*binom(x,3)*inv[3]*2*2;// 选3个位置(p0,p1,p0,p2),1/3产出率,p1和p2交换,前组和后组交换
  //    l0 < r0 = l1 < r1, l1 < r1 = l0 < r0
  ans += fac[x]*binom(x,3)*inv[6]*2;// 选3个位置(p0,p1,p1,p2),1/6产出率, 前组和后组交换
  //    4个坐标都不一样
  ans += fac[x]*binom(x,4)*6*ifac[4]*6;// 选4个位置(p0,p1,p2,p3),6/4!产出率, 6种p的交换

  // (B,C),(C,B), 固定的下标i,未固定的下标p,q,l
  rep(i,1,n+1) if(a[i] != -1) {
    // 互不相同
    // (p,i) (q,l)
    ans+=lp[i]*(x-l[a[i]])*fac[x-1]*binom(x-1,2)*inv[2]*2;//左侧,更大值,剩余排列,选2个位置,1/2产出率,对称x2
    // (i,p) (q,l)
    ans+=(x-lp[i])*l[a[i]]*fac[x-1]*binom(x-1,2)*inv[2]*2;//右侧,更小值,剩余排列,选2个位置,1/2产出率,对称x2
    // 有共用下标
    // (p,i) (p,l)
    ans+=sum(x-lp[i],x-1)*sum(l[a[i]],x-1)*fac[x-2]*2;//p,l下标枚举,值枚举,剩余排列,对称x2
    // (i,p) (l,p)
    ans+=sum(lp[i],x-1)*sum(x-l[a[i]],x-1)*fac[x-2]*2;//p,l下标枚举,值枚举,剩余排列,对称x2
    // (p,i) (l,p)
    ans+=binom(lp[i],2)*binom(x-l[a[i]],2)*fac[x-2]*2;//更小下标x2,更大值x2,剩余排列,对称x2
    // (i,p) (p,l)
    ans+=binom(x-lp[i],2)*binom(l[a[i]],2)*fac[x-2]*2;//更大下标x2,更小值x2,剩余排列,对称x2
  }

  // (B,B)
  rep(i,1,n+1) if(a[i] != -1) {
    // (i,p),(i,p)
    ans+=binom(x-lp[i],1)*binom(l[a[i]],1)*fac[x-1];//更大下标x1,更小值x1,剩余排列
    // (p,i),(p,i)
    ans+=binom(lp[i],1)*binom(x-l[a[i]],1)*fac[x-1];//更小下标x1,更大值x1,剩余排列
    // (i,p),(i,q)
    ans+=binom(x-lp[i],2)*binom(l[a[i]],2)*fac[x-2]*4;//更大下标x2,更小值x2,剩余排列,下标和值交换x4
    // (p,i),(q,i)
    ans+=binom(lp[i],2)*binom(x-l[a[i]],2)*fac[x-2]*4;//更小下标x2,更大值x2,剩余排列,下标和值交换x4
    // (p,i,i,q), (i,p,q,i)
    ans+=lp[i]*(x-lp[i])*l[a[i]]*(x-l[a[i]])*fac[x-2]*2;//小下标,大下标,大值,小值,剩余排列,对称x2
  }
  rep(i,1,n+1) if(a[i] != -1) rep(j,i+1,n+1) if(a[j] != -1) { // i < j, O(n^2)
    // (i,p,j,p) 更大坐标,更小值,剩余排列,交换ij
    ans+=(x-lp[j])*l[min(a[i],a[j])]*fac[x-1]*2;
    // (p,i,p,j) 更小坐标,更大值,剩余排列,交换ij
    ans+=lp[i]*(x-l[max(a[i],a[j])])*fac[x-1]*2;
    // (i,p,p,j) 更小坐标,更大值,剩余排列,交换ij
    ans+=(lp[j]-lp[i])*max(0,l[a[i]]-l[a[j]])*fac[x-1]*2;

    // (i,p,j,q) 选>j,选>i,选小值,再选大值,剩余排列,交换
    ans+=(x-lp[j])*(x-lp[i]-1)*(l[min(a[i],a[j])])*(l[max(a[i],a[j])]-1)*fac[x-2]*2;
    // (p,i,q,j) 选<i,选<j,选大值,再选小值,剩余排列,交换
    ans+=(lp[i])*(lp[j]-1)*(x-l[max(a[i],a[j])])*(x-l[min(a[i],a[j])]-1)*fac[x-2]*2;
    // (p,i,j,q) <i,>j,
    if(a[i] > a[j]) { // a[p] > a[i] > a[j] > a[q]
      ans+=(lp[i])*(x-lp[j])*(x-l[a[i]])*(l[a[j]])*fac[x-2]*2;
    }else { // a[p] > a[i], a[i] < a[j], a[j] > a[q]
      // a[p] > a[j]
      ans+=(lp[i])*(x-lp[j])*(x-l[a[j]])*(l[a[j]])*fac[x-2]*2;
      // a[j] > a[p] > a[i]
      ans+=(lp[i])*(x-lp[j])*(l[a[j]]-l[a[i]])*(l[a[j]]-1)*fac[x-2]*2;
    }

    // (i<p,q<j), a[i] > a[p], a[q] > a[j]
    mint posmul = 0;
    posmul += (lp[j]-lp[i])*(lp[j]-1); //    i < p < j, q < j
    posmul += (x-lp[j])*(lp[j]);       //    i < j < p, q < j
    if(a[j] > a[i]){ // a[q] > a[j] > a[i] > a[p]
      ans+=posmul*(l[a[i]])*(x-l[a[j]])*fac[x-2]*2;
    }else{ // a[i] > a[j]
      // a[i] > a[p] > a[j]
      ans+=posmul*(l[a[i]]-l[a[j]])*(x-l[a[j]]-1)*fac[x-2]*2;
      // a[i] > a[j] > a[p]
      ans+=posmul*(l[a[j]])*(x-l[a[j]])*fac[x-2]*2;
    }
  }
  printf("%d\n",ans.val());
  return 0;
}

提出情報

提出日時
問題 G - Inversion Squared
ユーザ cromarmot
言語 C++ 20 (gcc 12.2)
得点 625
コード長 5639 Byte
結果 AC
実行時間 222 ms
メモリ 3996 KiB

コンパイルエラー

Main.cpp: In function ‘ll read()’:
Main.cpp:9:21: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
    9 | ll read(){ll r;scanf("%lld",&r);return r;}
      |                ~~~~~^~~~~~~~~~~

ジャッジ結果

セット名 Sample All
得点 / 配点 0 / 0 625 / 625
結果
AC × 3
AC × 33
セット名 テストケース
Sample 00_sample_01.txt, 00_sample_02.txt, 00_sample_03.txt
All 00_sample_01.txt, 00_sample_02.txt, 00_sample_03.txt, 01_test_01.txt, 01_test_02.txt, 01_test_03.txt, 01_test_04.txt, 01_test_05.txt, 01_test_06.txt, 01_test_07.txt, 01_test_08.txt, 01_test_09.txt, 01_test_10.txt, 01_test_11.txt, 01_test_12.txt, 01_test_13.txt, 01_test_14.txt, 01_test_15.txt, 01_test_16.txt, 01_test_17.txt, 01_test_18.txt, 01_test_19.txt, 01_test_20.txt, 01_test_21.txt, 01_test_22.txt, 01_test_23.txt, 01_test_24.txt, 01_test_25.txt, 01_test_26.txt, 01_test_27.txt, 01_test_28.txt, 01_test_29.txt, 01_test_30.txt
ケース名 結果 実行時間 メモリ
00_sample_01.txt AC 1 ms 3940 KiB
00_sample_02.txt AC 1 ms 3700 KiB
00_sample_03.txt AC 1 ms 3768 KiB
01_test_01.txt AC 1 ms 3772 KiB
01_test_02.txt AC 1 ms 3728 KiB
01_test_03.txt AC 1 ms 3836 KiB
01_test_04.txt AC 1 ms 3624 KiB
01_test_05.txt AC 1 ms 3828 KiB
01_test_06.txt AC 58 ms 3872 KiB
01_test_07.txt AC 89 ms 3656 KiB
01_test_08.txt AC 1 ms 3856 KiB
01_test_09.txt AC 20 ms 3920 KiB
01_test_10.txt AC 20 ms 3728 KiB
01_test_11.txt AC 59 ms 3852 KiB
01_test_12.txt AC 33 ms 3644 KiB
01_test_13.txt AC 2 ms 3868 KiB
01_test_14.txt AC 2 ms 3724 KiB
01_test_15.txt AC 14 ms 3728 KiB
01_test_16.txt AC 184 ms 3732 KiB
01_test_17.txt AC 1 ms 3712 KiB
01_test_18.txt AC 71 ms 3656 KiB
01_test_19.txt AC 222 ms 3868 KiB
01_test_20.txt AC 49 ms 3740 KiB
01_test_21.txt AC 1 ms 3924 KiB
01_test_22.txt AC 91 ms 3920 KiB
01_test_23.txt AC 135 ms 3876 KiB
01_test_24.txt AC 140 ms 3764 KiB
01_test_25.txt AC 29 ms 3996 KiB
01_test_26.txt AC 190 ms 3876 KiB
01_test_27.txt AC 188 ms 3736 KiB
01_test_28.txt AC 193 ms 3868 KiB
01_test_29.txt AC 193 ms 3784 KiB
01_test_30.txt AC 189 ms 3656 KiB