Problem:
Problem I: Coin and Die

Problem

表と裏のあるコインと $1$ から $N$ までの目があるサイコロがある。Gachoくんはこれらを用いて以下のゲームをして遊ぶことにした。

ゲームは最初に得点が $0$ の状態から始まり、以下の手順で進められる。

サイコロを $1$ 回振り、そのとき出た目の数を得点に加算する

現在の得点が $K$ 以上ならゲームクリアとなりゲームを終了する

現在の得点が $K$ 未満ならコインを投げ表が出れば1.に戻り、裏が出ればゲームオーバーとなりゲームを終了する

コインは投げると $A\%$の確率で表になり、 $(100-A)\%$の確率で裏になる。また、サイコロは振ると、それぞれの目が等確率で出現する。

このとき、一度のゲームでGachoくんがゲームクリアすることができる確率を求めよ。

求める確率を互いに素な整数 $P, Q$ を用いて $\frac{P}{Q}$ と表したとき、 $R \times Q \equiv P\bmod 998244353$ となる $0$ 以上 $998244352$ 以下の整数 $R$ を出力せよ。この問題の制約下で、このような $R$ は必ず一意に存在する。

Input

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

$N$ $K$ $A$

$N, K, A$ が空白区切りで一行に与えられる。

Constraints

入力は以下の条件を満たす。

$1 \leq N \leq 10^5 $

$1 \leq K \leq 10^5 $

$1 \leq A \leq 99 $

入力はすべて整数

Output

ゲームをクリアすることができる確率を互いに素な整数 $P, Q$を用いて $\frac{P}{Q}$ と表したとき、$R \times Q\equiv P\bmod 998244353$ となる $0$ 以上 $998244352$ 以下の整数 $R$ を出力せよ。

Sample Input 1

1 1 50

Sample Output 1

1

Sample Input 2

2 2 10

Sample Output 2

648858830

Sample Input 3

6 10 99

Sample Output 3

650893870

Solution in C (judge verdict: Accepted)

#include <stdio.h>
#include <stdlib.h>
#define ll long long
#define rep(i,l,r)for(ll i=l;i<r;i++)
#define max(p,q)((p)>(q)?(p):(q))
#define min(p,q)((p)<(q)?(p):(q))
ll pom(ll a,ll n,int m){ll x=1;for(a%=m;n;n/=2)n&1?x=x*a%m:0,a=a*a%m;return x;}
#define invp(a,p)pom(a,p-2,p)
#define MOD 998244353

//セグ木ここから
//*
//↓ここを変える
typedef struct atai{ll a;}atai;
atai xx(atai x,atai y){
	atai r;
	r.a=(x.a+y.a)%MOD;
	return r;
}
atai aid={0};
//↑ここを変える

int segNUM;
atai *segN,*seg;
void seguse(int n){
	segN=(atai*)calloc(2*n,sizeof(atai));
	segNUM=n;
	seg=segN+segNUM;
	rep(i,1,2*segNUM)segN[i]=aid;
}
//seg[]に値を与えてから初期化
void seginit(){for(int node=segNUM-1;node;node--)segN[node]=xx(segN[node*2],segN[node*2+1]);}
void segupdate(int node,atai x){
	//seg[node]をxに更新
	node+=segNUM;
	segN[node]=x;
	while(node/=2)segN[node]=xx(segN[node*2],segN[node*2+1]);
}

atai segcalcsub(int l,int r,int k,int cl,int cr){
	if(l>=r)return aid;
	//完全に含むとき
	if(l<=cl&&cr<=r)return segN[k];

	int cm=(cl+cr)/2;
	//左側だけ
	if(r<=cm)return segcalcsub(l,r,2*k  ,cl,cm);
	//右側だけ
	if(cm<=l)return segcalcsub(l,r,2*k+1,cm,cr);
	//両方
	return xx(segcalcsub(l,r,2*k,cl,cm),segcalcsub(l,r,2*k+1,cm,cr));
}
atai segcalc(int l,int r){return segcalcsub(l,r,1,0,segNUM);}
//セグ木ここまで
//*/

int main(){
	int n,k,p;
	scanf("%d%d%d",&n,&k,&p);
	int prob=p*invp(100,MOD)%MOD*invp(n,MOD)%MOD;
	seguse(1<<18);
	seg[0].a=1;
	seginit();
	rep(i,1,n+k){
		ll temp=segcalc(max(0,i-n),min(i,k)).a;
		atai x={temp*prob%MOD};
		segupdate(i,x);
	}
	printf("%lld\n",segcalc(k,n+k).a*invp(p,MOD)%MOD*100%MOD);
}