結果

問題 No.1967 Sugoroku Optimization
ユーザー HIcoderHIcoder
提出日時 2023-07-23 13:05:42
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 1,153 ms / 2,000 ms
コード長 4,096 bytes
コンパイル時間 1,399 ms
コンパイル使用メモリ 122,124 KB
実行使用メモリ 98,152 KB
最終ジャッジ日時 2023-10-24 19:23:50
合計ジャッジ時間 11,309 ms
ジャッジサーバーID
(参考情報)
judge12 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,348 KB
testcase_01 AC 2 ms
4,348 KB
testcase_02 AC 2 ms
4,348 KB
testcase_03 AC 1,153 ms
98,152 KB
testcase_04 AC 3 ms
4,348 KB
testcase_05 AC 1,007 ms
88,120 KB
testcase_06 AC 1,064 ms
93,928 KB
testcase_07 AC 4 ms
4,348 KB
testcase_08 AC 749 ms
67,000 KB
testcase_09 AC 511 ms
50,896 KB
testcase_10 AC 222 ms
25,816 KB
testcase_11 AC 29 ms
6,796 KB
testcase_12 AC 639 ms
61,192 KB
testcase_13 AC 308 ms
32,152 KB
testcase_14 AC 16 ms
5,556 KB
testcase_15 AC 17 ms
5,584 KB
testcase_16 AC 27 ms
6,564 KB
testcase_17 AC 32 ms
7,144 KB
testcase_18 AC 3 ms
4,348 KB
testcase_19 AC 2 ms
4,348 KB
testcase_20 AC 1,125 ms
97,888 KB
testcase_21 AC 2 ms
4,348 KB
testcase_22 AC 1,141 ms
98,152 KB
testcase_23 AC 677 ms
60,664 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include<iostream>
#include<set> 
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include<map>
#include<numeric>
#include<queue>
#include<cmath>
#include <unordered_set>
#include<cassert>
using namespace std;
typedef long long ll;
const ll INF=1LL<<60;
typedef pair<int,int> P;
typedef pair<int,P> PP;
const ll MOD=998244353;


//binary_indexed_tree bit;
struct binary_indexed_tree{
    int N;
    vector<ll> bit;
    
    //binary_indexed_tree(){};//ただのコンストラクタ
    
    binary_indexed_tree(int n){
        bit = vector<ll>(n+1,0);
        N=n;
    }

    ~binary_indexed_tree(){
        vector<ll>().swap(bit);
    }



    ll addition(ll x, ll y){
        return (x+y)%MOD;
    }
    void add(int x,ll a){
        x++;//1から始めるための補正
        //for(int i=x; i<=N; i+=(i&-i)) bit[i] = addition(bit[i],a);
        while(x<=N){
            bit[x] = addition(bit[x],a);
            x += x&-x;
        }
    }
    ll sum(int x){
        x++;//1から始まることに注意
        ll ret=0;
        //for(int i=x; i>0; i-=(i&-i)) ret = addition(ret,bit[i]);
        while(x>0){
            ret = addition(ret,bit[x]);
            x -= x&-x;
        }
        
        return ret;
    }

    //[l,r]の範囲
    ll get(int l,int r){
        if(r>N) return 0;//配列の外へのアクセス
        if(l>r) return 0;//本来は l<=r となるのでおかしい
        if(l==0) return sum(r);//[0,r]//ここでoutなわけか
        else return (sum(r) - sum(l-1)+MOD)%MOD;
    }


    
};



ll mod_pow(ll x,ll y,ll mod){
    ll res=1;
    while(y>0){
        if(y&1){
            res*=x;
            res%=mod;
        }
        x*=x;
        x%=mod;
        y/=2;
    }

    return res;
}

int main(){
    int N,K;
    cin>>N>>K;

    vector visit(N+1,vector<bool>(K+1,false));
    vector memo(N+1,vector<ll>(K+1,0));
   
    vector dp(N+1,vector<ll>(K+1,0));

    //vector<ll> sum(K+1,0);
    //vector sum(N+1,vector<ll>(K+1,0));

     binary_indexed_tree bit(N+2);
   vector<binary_indexed_tree> bitarray(K+2,bit);

    for(int k=0;k<=K;k++){
        dp[N][k]=1;
        bitarray[k].add(N,1);
        //sum[k]=1;
        //sum[N][k-1]=1;
    }
    /*
    for(int i=N-1;i>=0;i--){
        for(int k=K;k>=0;k--){
            
            ll sum=0;         
            
            if(k-1>=0){
                
                for(int t=i+1;t<=N;t++){
                    sum+=dp[t][k-1];
                    sum%=MOD;
                }
            }

            ll a=N-i;
            ll inv=mod_pow(a,MOD-2,MOD); //1/a
            dp[i][k]=sum*inv%MOD;
        }
    }
    */

  

    for(int i=N-1;i>=0;i--){


        for(int k=K;k>=0;k--){
            
        
            ll tmpsum=0;         
            
            if(k-1>=0){
                /*
                for(int t=i+1;t<=N;t++){
                    sum+=dp[t][k-1];
                    sum%=MOD;
                }
                */
                //tmpsum=sum[i][k-1];
                
                //t=[i+1,N]
                tmpsum=bitarray[k-1].get(i+1,N);

            }

            ll a=N-i;
            ll inv=mod_pow(a,MOD-2,MOD); //1/a
            dp[i][k]=tmpsum*inv%MOD;

            bitarray[k].add(i,dp[i][k]);
            
        }
    }

    cout<<dp[0][K]<<endl;
    return 0;

    /*

    //今,nowのマスにいる
    //残りk回回せる
    auto dfs=[&](auto f,int now,int k)->ll{
        
        if(now==N && k>=0) return 1;
        
        if(k>0 && now==N-1) return 1; //次で勝てる
        
        


        if(k==0) return 0; //もう回せないので
        if(visit[now][k]) memo[now][k];

        ll best=0;
        
        ll a=N-now;

        //cout<<"now="<<now<<",k="<<k<<endl;
            
            ll inv=mod_pow(a,MOD-2,MOD); //1/a
        for(int t=1;t<=a;t++){
            //cout<<"t="<<t<<endl;
            best+=f(f,now+t,k-1)*inv%MOD;
            best%=MOD;
        }
        
        visit[now][k]=true;
        return memo[now][k]=best;

    };

    ll ans=dfs(dfs,0,K);
    cout<<ans<<endl;
    */


}
0