PKUWC & SC 2018 records the title brush
minimax
Segment tree combined title, does not seem to depend on the binary tree.
Before writing the hasty explanations here: PKUWC2018 Minimax
Slay the Spire
Strengthening multiples noted that strengthening the cards are larger than \ (1 \) is a positive integer, it can be found to strengthen as much as possible to strengthen.
With \ (F (x, y) \) represents the strengthening Card Draw \ (x \) Zhang played \ (y \) ratio of sheets and
With \ (G (x, y) \) means that the attack Card Draw \ (x \) Zhang played \ (y \) Zhang's attack and
Then we enumerate how many smoked attack cards, the use of more than two functions can be calculated answer.
As for how to calculate the two function codes to see.
#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
const int sz=3e3+7;
const int mod=998244353;
int T;
int ans;
int n,m,k;
int a[sz],b[sz];
int inv[sz],fac[sz],ifac[sz];
int sum[sz],f[sz][sz],g[sz][sz];
void init(){
fac[0]=ifac[0]=1;
fac[1]=ifac[1]=inv[1]=1;
for(int i=2;i<sz;i++){
inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
fac[i]=1ll*i*fac[i-1]%mod;
ifac[i]=1ll*inv[i]*ifac[i-1]%mod;
}
}
int C(int n,int m){
return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
int F(int x,int y){
//抽出x张强化牌,y张打出去的效用和
if(x<y) return 0;
if(y==0) return C(n,x);
int ret=0;
rep(i,x-y+1,n-y+1)
ret=(ret+1ll*f[y][i]*C(i-1,x-y)%mod)%mod;
return ret;
}
int G(int x,int y){
//抽出x张攻击牌,y张打出去的效用和
if(x<y) return 0;
if(y==0) return 0;
int ret=0;
rep(i,x-y+1,n-y+1)
ret=(ret+1ll*g[y][i]*C(i-1,x-y)%mod)%mod;
return ret;
}
int main(){
init();
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&k);
rep(i,1,n) rep(j,1,n) f[i][j]=g[i][j]=0;
rep(i,1,n) scanf("%d",&a[i]);
rep(i,1,n) scanf("%d",&b[i]);
sort(a+1,a+n+1);
sort(b+1,b+n+1);
rep(i,1,n){
f[1][i]=a[i];
sum[i]=(sum[i-1]+f[1][i])%mod;
}
rep(i,2,n){
rep(j,1,n-i+1)
f[i][j]=1ll*a[j]*((sum[n]-sum[j]+mod)%mod)%mod;
rep(j,1,n)
sum[j]=(sum[j-1]+f[i][j])%mod;
}
rep(i,1,n){
g[1][i]=b[i];
sum[i]=(sum[i-1]+g[1][i])%mod;
}
rep(i,2,n){
rep(j,1,n-i+1)
g[i][j]=(1ll*b[j]*C(n-j,i-1)%mod+(sum[n]-sum[j]+mod)%mod)%mod;
rep(j,1,n)
sum[j]=(sum[j-1]+g[i][j])%mod;
}
ans=0;
rep(i,max(m-n,0),min(n,m)){
int j=m-i;
ans=(ans+1ll*F(i,min(i,k-1))*G(j,max(k-i,1))%mod)%mod;
}
printf("%d\n",ans);
}
}
Landlords
I can not write, can not write in this life.
Random algorithm
Enumeration is not selected set \ (S \) (non-selected set is already connected to some of these independent and separate sets, and sets the current point)
Each time, select a new point into the independent set, then it will be added at some point can not be selected.
As long as these points are placed on the back of a new independent set point on it, it is a contribution to the number of combinations.
Then gone.
#include<bits/stdc++.h>
using namespace std;
const int sz=24;
const int mod=998244353;
int n,m;
int u,v,t;
int link[sz];
int bit[1<<20];
int fac[sz],ifac[sz],inv[sz];
int dp[1<<20],g[1<<20];
void init(){
fac[0]=ifac[0]=1;
fac[1]=ifac[1]=inv[1]=1;
for(int i=2;i<sz;i++){
inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
fac[i]=1ll*i*fac[i-1]%mod;
ifac[i]=1ll*inv[i]*ifac[i-1]%mod;
}
}
int C(int n,int m){
return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
int main(){
init();
scanf("%d%d",&n,&m);
t=1<<n;
for(int i=1;i<=n;i++) link[i]|=1<<(i-1);
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
link[u]|=1<<(v-1);
link[v]|=1<<(u-1);
}
for(int i=1;i<t-1;i++) bit[i]=bit[i>>1]+(i&1);
dp[0]=1,g[0]=0;
for(int i=0;i<t;i++){
for(int j=1;j<=n;j++)
if(((i>>(j-1))&1)==0){
int s=i|link[j],p=s^i;
if(g[i]+1<g[s]) continue;
else if(g[i]+1==g[s])
dp[s]=(dp[s]+1ll*dp[i]*C(n-bit[i]-1,bit[p]-1)%mod*fac[bit[p]-1]%mod)%mod;
else{
g[s]=g[i]+1;
dp[s]=1ll*dp[i]*C(n-bit[i]-1,bit[p]-1)%mod*fac[bit[p]-1]%mod;
}
}
}
int ans=1ll*dp[t-1]*ifac[n]%mod;
printf("%d\n",ans);
}
Hunters kill
You think I'd do?
No, I will not.
Random Walk
\ (min-max \) inclusion and exclusion good title
After re \ (FMT \) click on it.
#include<bits/stdc++.h>
#define go(x) for(int i=head[x];i;i=edge[i].nxt)
#define now edge[i].v
using namespace std;
const int sz=20;
const int mod=998244353;
int S;
int t;
int k,x;
int n,q,rt;
int u,v,cnt;
int head[sz];
int a[sz],b[sz],d[sz];
int s[1<<20],bit[1<<20];
struct Edge{
int v,nxt;
}edge[sz<<1];
int qpow(int x,int y){
int ret=1;
for(;y;y>>=1,x=1ll*x*x%mod) if(y&1) ret=1ll*x*ret%mod;
return ret;
}
void add(int u,int v){
edge[++cnt]=(Edge){v,head[u]};head[u]=cnt;
edge[++cnt]=(Edge){u,head[v]};head[v]=cnt;
}
void dfs(int x,int fa){
int asum=0,bsum=0;
go(x) if(now!=fa){
dfs(now,x);
asum=(asum+a[now])%mod;
bsum=(bsum+b[now])%mod;
}
if(S>>(x-1)&1) a[x]=b[x]=0;
else{
int inv=qpow((d[x]-asum+mod)%mod,mod-2);
a[x]=inv,b[x]=1ll*inv*(d[x]+bsum)%mod;
}
}
int main(){
scanf("%d%d%d",&n,&q,&rt);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
d[u]++;
d[v]++;
add(u,v);
}
t=1<<n;
for(S=1;S<t;S++){
dfs(rt,0);
bit[S]=bit[S>>1]^(S&1);
s[S]=bit[S]?b[rt]:(mod-b[rt])%mod;
}
for(int i=1;i<t;i<<=1)
for(int j=0;j<t;j+=2*i)
for(int k=0;k<i;k++)
s[i+j+k]=(s[i+j+k]+s[j+k])%mod;
while(q--){
S=0;
scanf("%d",&k);
while(k--){
scanf("%d",&x);
S|=1<<(x-1);
}
printf("%d\n",s[S]);
}
}
Real rankings
Simple question, take \ (two-point \) just to make trouble on it.
Before writing the hasty explanations here: PKUSC2018 real rankings
Maximum prefix and
It seems to be a compressed state \ (DP \) ?
It seems a long time ago I wrote (or I might give someone else Hu finished let him help me write), do not remember.
First muttered.
Main fighting ground
Sorry, I will not write.
Interstellar
No, I muttered.
Fairy game
The \ (border \) becomes the loop section on it, then \ (FFT \) click on it.
Before writing the hasty explanations here: PKUSC2018 fairy game
PKUSC
It does not seem difficult to think.
Only need to every point within the polygon and then adding the calculated probability can be obtained the desired.
The contribution of each point to probably make it to the distance from the origin of the circle, to see how much of an arc within the polygon.
But next door to see the ATS Gangster liver the liver has not come out one day sooner, I really lack courage.