杭电多校赛2020第一场VP实录

D - Distinct Sub-palindromes

思博题。
A C   C o d e \mathcal AC\ Code

#include<cstdio>

int main(){
int T;scanf("%d",&T);
for(;T--;){
int n;scanf("%d",&n);
if(n == 1) puts("26");
if(n == 2) puts("676");
if(n == 3) puts("17576");
if(n > 3) puts("15600");
}
}

K - Minimum Index

d u v a l duval 算法求每个前缀的最小后缀,
根据算法的循环维护。

#include<bits/stdc++.h>
#define maxn 1000006
#define mod 1000000007
using namespace std;

int n,ans[maxn];
char s[maxn];

int main(){
    int T;
    scanf("%d",&T);
    memset(ans,-1,sizeof ans);
    for(;T--;){
        scanf("%s",s);
        int ret = 0;
        n = strlen(s);
        ans[0] = 0;
        for(int i=0;i<n;){
            int j=i,k=i+1;
            for(;k < n && s[j] <= s[k];k++){
                if(s[j] < s[k]) j = i , ans[k] = j;
                else{
                    ans[k] = ans[j] + k - j;
                    j ++;
                }
            }
            ans[k] = k;
            int L = k - j;
            for(;i <= j;)
                i += L;
        }
        for(int i=n-1;i>=0;i--)
            ret = (ret * 1112ll + ans[i] + 1) % mod,ans[i] = -1;
        printf("%d\n",ret);
    }

}

E - Fibonacci Sum

a n s = i = 0 K ( K i ) ( 1 ) i 5 K × 1 ( 1 + 5 2 ) i c ( n + 1 ) ( 1 5 2 ) ( K i ) c ( n + 1 ) 1 ( 1 + 5 2 ) i c ( 1 5 2 ) ( K i ) c ans = \sum_{i=0}^K\frac {\binom Ki (-1)^i}{\sqrt 5^K} \times \frac {1 - (\frac {1+\sqrt 5}2)^{ic(n+1)}(\frac {1-\sqrt 5}2)^{(K-i)c(n+1)}}{1- (\frac {1+\sqrt 5}2)^{ic}(\frac {1-\sqrt 5}2)^{(K-i)c}}
容易发现只需要求 ( 1 + 5 2 ) (\frac {1+\sqrt 5}2) ( 1 5 2 ) (\frac {1-\sqrt 5}2) 的任意次幂,以及 K K 个逆元,还有一些组合数。
可以通过分块预处理幂和线性求 K K 个数的逆元得到 O ( m o d + T ( K + log K ) ) O(\sqrt {mod} + T(K + \log K)) 的做法。

A C   C o d e \mathcal AC \ Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define mod 1000000009
#define LL long long
#define phi 1000000008
#define S 40005
#define maxn 100005
const int FV = 383008016 , C[2] = {383008017ll * ((mod+1) / 2) % mod , (1 - 383008016ll) * ((mod+1) / 2) % mod}; 

int Pow(int b,int k){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1) r=1ll*r*b%mod;return r; }
const int FIV = Pow(FV , mod-2);
int pw[2][S + 5],pwS[2][S + 5],inv[maxn];
int it[maxn] , sm[maxn] , iv[maxn] , is0[maxn];
int calc(int t,int c){
	return 1ll * pwS[t][c / S] * pw[t][c % S] % mod;
}

int main(){
	inv[0] = inv[1]= 1;
	rep(i,2,maxn-1) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
	rep(t,0,1){
		pw[t][0] = pwS[t][0] = 1;
		rep(i,1,S) pw[t][i] = pw[t][i-1] * 1ll * C[t] % mod;
		rep(i,1,S) pwS[t][i] = pwS[t][i-1] * 1ll * pw[t][S] % mod; 
	}
	int T;scanf("%d",&T);
	for(int K;T--;){
		LL n , c;
		scanf("%lld%lld%d",&n,&c,&K);
		LL N = n % mod;
		n %= phi , c %= phi;
		int ans = 0 , Binom = (K&1 ? -1 : 1);
		rep(i,0,K){
			it[i] = (1 - calc(0,1ll * i * c % phi) * 1ll * calc(1,1ll * (K-i) * c % phi)) % mod;
			if(it[i]) is0[i] = 0;
			else is0[i] = 1 , it[i] = 1;
		}
		rep(i,0,K) sm[i] = 1ll * (i ? sm[i-1] : 1ll) * it[i] % mod;
		iv[K] = Pow(sm[K] , mod-2);
		per(i,K,0){
			if(i) iv[i-1] = 1ll * iv[i] * it[i] % mod;
			iv[i] = 1ll * iv[i] * (i ? sm[i-1] : 1ll) % mod;
		}
		rep(i,0,K){
			if(!is0[i])
				ans = (ans + 1ll * Binom * (1 - 1ll * calc(0,1ll * c * i % phi * (n+1) % phi) * calc(1,1ll * c * (K-i) % phi * (n+1) % phi) % mod) % mod * iv[i]) % mod;
			else 
				ans = (ans + 1ll * Binom * (N + 1)) % mod;
			Binom = -1ll * Binom * (K-i) % mod * inv[i+1] % mod; 
		}
		ans = 1ll * ans * Pow(FIV , K) % mod;
		printf("%d\n",(ans+mod)%mod);
	}
}

F - Finding a MEX

度数小的往度数大的连边,那么出度 n \leq \sqrt n ,修改时只需要对于出边修改,询问时额外加上入边即可, O ( n n log n ) O(n\sqrt n \log n) ,借树状数组的优异表现和不带 log \log 的算法差不多。
但是度数分治可以做到 O ( n n ) O(n\sqrt n)

A C   C o d e \mathcal AC \ Code

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define maxn 100005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;

char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct) ? 0:*cs++)
void read(int &res){
	char ch;
	for(;!isdigit(ch=getc()););
	for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}

int n,m,A[maxn];
int sx[maxn],ty[maxn],d[maxn];
vector<int>G[maxn];
int vis[maxn],tim;
vector<int>cnt[maxn],st[maxn];

void upd(vector<int>&u,int x,int v){ for(x++;x<u.size();x+=x&-x) u[x] += v; }
int main(){
	int T;read(T);
	for(;T--;){
		read(n),read(m);
		rep(i,1,n) read(A[i]);
		rep(i,1,m) read(sx[i]),read(ty[i]),d[sx[i]]++,d[ty[i]]++;
		rep(i,1,m){
			if(d[sx[i]] > d[ty[i]]) swap(sx[i],ty[i]);
			G[sx[i]].push_back(ty[i]);
		}
		rep(i,1,n){
			cnt[i].resize(d[i] + 1);
			st[i].resize(d[i] + 2);
		}
		rep(i,1,n) rep(j,0,G[i].size()-1){
			int v = G[i][j];
			if(A[i] <= d[v] && cnt[v][A[i]] ++  == 0) upd(st[v],A[i],1);
		}
		int q;read(q);
		for(int op,u,x;q--;){
			read(op) , read(u);
			if(op == 1){
				read(x);
				rep(j,0,G[u].size()-1){
					int v = G[u][j];
					if(A[u] <= d[v] && cnt[v][A[u]] -- == 1) upd(st[v],A[u],-1);
					if(x <= d[v] && cnt[v][x] ++ == 0) upd(st[v],x,1);
				}
				A[u] = x;
			}
			else{
				++tim;
				rep(j,0,G[u].size()-1){
					int v = G[u][j];
					if(A[v] <= d[u] && cnt[u][A[v]] ++ == 0) upd(st[u],A[v],1);
				}
				int L = 0;
				per(i,log2(st[u].size()),0){
					L += 1 << i;
					if(L >= st[u].size() || st[u][L] != 1 << i) L -= 1 << i;
				}
				printf("%d\n",L);
				rep(j,0,G[u].size()-1){
					int v = G[u][j];
					if(A[v] <= d[u] && cnt[u][A[v]] -- == 1) upd(st[u],A[v],-1);
				}
			}
		}
		rep(i,1,n) cnt[i].clear() , st[i].clear() , G[i].clear() , d[i] = 0;
	}
}

I - Leading Robots

发现在这个题中两个抛物线只有一个有用的交点,随便单调栈维护一下即可。
A C   C o d e \mathcal AC \ Code

#include<bits/stdc++.h>
#define maxn 50005
#define LL unsigned long long
using namespace std;

int n,c[maxn],tg[maxn];
LL p[maxn],a[maxn];
bool cmp(const int &u,const int &v){ return p[u] == p[v] ? a[u] > a[v] : p[u] > p[v]; }
int q[maxn],R;

int main(){
	int T;
	scanf("%d",&T);
	for(;T--;){
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%lld%lld",&p[i],&a[i]);
			tg[i] = 0;
			p[i] <<= 1;
			c[i] = i;
		}
		sort(c+1,c+1+n,cmp);
		R = 0;
		for(int i=1;i<=n;i++){
			int u = c[i];
			if(R && (a[q[R]] >= a[u])){
				if(a[q[R]] == a[u] && p[q[R]] == p[u])
					tg[q[R]] = 1;
				continue;
			}
			for(;R >= 2 && (p[q[R]] - p[u]) * (a[u] - a[q[R-1]]) <= (p[q[R-1]] - p[u]) * (a[u] - a[q[R]]);R--);
			q[++R] = u;
		}
		int ans = R;
		for(int i=1;i<=R;i++) if(tg[q[i]]) ans--;
		printf("%d\n",ans);
	}
}

L - Mow

因为是凸多边形,所以是经典题。
往内缩 r r 然后求半平面交即可(凸多边形才行。)
A C   C o d e \mathcal AC \ Code

#include<bits/stdc++.h>
#define maxn 305
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define eps 1e-8
#define db double
#define Ct const
#define Pi 3.1415926535897932384626433832795
using namespace std;

int dcmp(const db &x){ return x < -eps ? -1 : x > eps ? 1 : 0; }
db sqr(db x){ return x * x; }
struct Pt {
	db x,y;
	Pt (Ct db &x=0,Ct db &y=0):x(x),y(y){}
	Pt operator +(Ct Pt &B)Ct{ return Pt(x + B.x , y + B.y); }
	Pt operator -(Ct Pt &B)Ct{ return Pt(x - B.x , y - B.y); }
	Pt operator *(Ct db &B)Ct{ return Pt (x * B , y * B); }  
	Pt norm()Ct{ return Pt(-y,x); }
	Pt elen(db l){ db t = sqrt(sqr(x) + sqr(y)); return Pt(x / t * l , y / t * l); }
	db dist(Ct Pt &B)Ct{ return sqrt(sqr(x - B.x) + sqr(y - B.y)); }
	db operator *(Ct Pt &B)Ct{ return x * B.y - y * B.x; }
}P[maxn],qp[maxn];
int n;
db r,A,B;
Pt ITP(Ct Pt &p1,Ct Pt &v1,Ct Pt &p2,Ct Pt &v2){ return p1 + v1 * (((p2 - p1) * v2) / (v1 * v2));}
struct Line{
	Pt S,T;
	db ang;
	Line(Ct Pt &S=0,Ct Pt &T=0):S(S),T(T){ ang = atan2(T.y - S.y , T.x - S.x); }
	bool operator <(Ct Line &B)Ct{ return dcmp(ang - B.ang) ? ang < B.ang : (B.T - B.S) * (T - B.S) <= 0; }
}L[maxn],q[maxn];

int main(){
	int T;
	for(scanf("%d",&T);T--;){
		scanf("%d%lf%lf%lf",&n,&r,&A,&B);
		db area = 0;
		rep(i,1,n) scanf("%lf%lf",&P[i].x,&P[i].y);
		rep(i,1,n) area += P[i] * P[i % n + 1];
		area *= 0.5;
		if(area < 0){
			reverse(P+1,P+n+1);
			area = - area;
		}
		if(B > A){
			printf("%.10lf\n",A * area);
			continue;
		}
		rep(i,1,n){
			Pt t = (P[i % n + 1] - P[i]) . norm() . elen(r);
			L[i] = Line(P[i] + t , P[i % n + 1] + t);
		}
		sort(L+1,L+1+n);
		int ql = 0 , qr = -1;
		rep(i,1,n) if(i == 1 || dcmp(L[i].ang - L[i-1].ang)){
			for(;qr - ql + 1 >= 2 && (qp[qr] - L[i].S) * (L[i].T - L[i].S) >= 0;qr--);
			for(;qr - ql + 1 >= 2 && (qp[ql + 1] - L[i].S) * (L[i].T - L[i].S) >= 0;ql++);
			q[++qr] = L[i];
			if(qr - ql + 1 >= 2) qp[qr] = ITP(q[qr-1].S,q[qr-1].T-q[qr-1].S,L[i].S,L[i].T-L[i].S);
		}
		for(;qr - ql + 1 >= 3 && (qp[qr] - q[ql].S) * (q[ql].T - q[ql].S) >= 0;qr--);
		if(qr - ql + 1 >= 3){
			qp[ql] = ITP(q[qr].S,q[qr].T-q[qr].S,q[ql].S,q[ql].T-q[ql].S);
			db ia = qp[qr] * qp[ql] , C = qp[qr] . dist(qp[ql]);
			rep(i,ql,qr-1) ia += qp[i] * qp[i+1] , C += qp[i].dist(qp[i+1]);
			ia *= 0.5;
			ia += C * r + r * r * Pi;
			area -= ia;
			printf("%.10lf\n",area * A + ia * B);
		}
		else
			printf("%.10lf\n",A * area);
	}
}

C - Cookies

注意到这个 divmed(n) \operatorname{divmed(n)} 函数就是 n \leq \sqrt n 的最大因数。
可以用埃氏筛法 O ( ( r l ) ln r ) O((r-l)\ln \sqrt r) 求出 i = l r divmed(i) \sum_{i=l}^r \operatorname{divmed(i)}
于是乎我们可以分段打表。

打表代码:
A C   C o d e \mathcal AC \ Code

#include<bits/stdc++.h>
#define maxn 2500000
#define LL long long
using namespace std;

int f[maxn+5];

int main(){
	
	freopen("1.in","w",stdout);
	
	for(LL i=maxn;i<=1e10;i+=maxn){
		int lim = sqrt(i);
		memset(f,0,sizeof f);
		for(int j=1;j<=lim;j++)
			for(LL k = max(1ll * j * j , (i - maxn + 1 + j - 1) / j * j) ; k <= i ; k += j)
				f[k - i + maxn] = max(f[k - i + maxn] , j);
		LL ans = 0;
		for(int j=1;j<=maxn;j++)
			ans += f[j];
		printf("%lld\n",ans);
	}
}

A C   C o d e \mathcal AC \ Code

#include<bits/stdc++.h>
#define maxn 5000000
#define LL long long
using namespace std;

int f[maxn+5];
LL n,m,K,p[maxn];
LL a[maxn + 5] = {
	/// the table ..
};

LL calc(LL l,LL r){
	int lim = sqrt(r);
	memset(f,0,sizeof f);
	for(int i=1;i<=lim;i++)
		for(LL k = max(1ll * i * i , (l + i - 1) / i * i); k <= r; k += i)
			f[k - l] = max(f[k - l] , i);
	LL ans = 0;
	for(int i=0;i<=r-l;i++)
		ans += f[i];
	return ans;
}

int main(){
	int T;
	for(int i=1;i<=maxn;i++) a[i] += a[i-1];
	for(scanf("%d",&T);T--;){
		scanf("%lld%lld%lld",&n,&m,&K);
		for(int i=1;i<=m;i++) scanf("%lld",&p[i]);
		for(int i=m;i>=1;i--){
			LL t = (K - 1) / (p[i] - 1);
			K += t;
			if(K > n)
				break;
		}
		if(K > n) puts("-1");
		else{
			LL t = K / maxn;
			if(K - t * maxn < (t + 1) * maxn - K){
				LL ans = a[t] + calc(t * maxn + 1 , K);
				printf("%lld\n",ans);
			}
			else{
				LL ans = a[t+1] - calc(K+1,(t+1) * maxn);
				printf("%lld\n",ans);
			}
		}
	}
}

J - Math is Simple

g n = a < b , gcd ( a , b ) = 1 , a + b = n 1 a b = 1 n a < b , gcd ( a , b ) = 1 , a + b = n 1 a + 1 b g_n = \sum_{a<b,\gcd(a,b)=1,a+b=n} \frac 1{ab} = \frac 1n\sum_{a<b,\gcd(a,b)=1,a+b=n} \frac 1a + \frac 1b
对于 n > 1 n\gt1 ,有:
g n = 1 n i n [ gcd ( i , n ) = 1 ] 1 i = 1 n p n μ ( p ) 1 p i = 1 n p 1 i g_n = \frac 1n\sum_{i\leq n} [\gcd(i,n)=1]\frac 1i=\frac 1n\sum_{p|n} \mu(p)\frac 1p\sum_{i=1}^{\frac np} \frac 1i
对于后面的调和级数 O ( n ) O(n) 预处理后即可以分解质因数的复杂度 + d ( n ) +d(n) 求出 g n g_n
对于 f n = 1 a < b n , gcd ( a , b ) = 1 , a + b n 1 a b f_n = \sum_{1\leq a \lt b\leq n,\gcd(a,b)=1,a+b\geq n} \frac 1{ab}
= 1 a < b n 1 , gcd ( a , b ) = 1 , a + b n 1 1 a b 1 a < b n 1 , gcd ( a , b ) = 1 , a + b = n 1 1 a b + a < n , gcd ( a , b = n ) = 1 1 a b =\sum_{1\leq a \lt b\leq n-1,\gcd(a,b)=1,a+b\geq n-1} \frac 1{ab} - \sum_{1\leq a \lt b\leq n-1,\gcd(a,b)=1,a+b = n-1} \frac 1{ab} +\sum_{a \lt n , \gcd(a,b=n) = 1} \frac 1{ab}
容易发现这就是 f n 1 + g n g n 1 f_{n-1} + g_n - g_{n-1}
所以对于 n > 2 n \gt2 ,有 f n = f 2 g 2 + g n = g n + 1 2 f_n = f_2 - g_2 + g_n = g_n + \frac 12

A C   C o d e \mathcal AC \ Code

#include<bits/stdc++.h>
#define mod 998244353
#define maxn 100000008
#define iv2 499122177ll
using namespace std;

int h[maxn];
int Pow(int b,int k){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1)r=1ll*r*b%mod; return r; }
int n;
int p[30] , c[30] , cnt;
int ans;

void dfs(int u,int d,int mu){
	if(u == cnt + 1){
		ans = (ans + 1ll * mu * h[n / d] % mod * Pow(d , mod-2)) % mod;
		return;
	}
	dfs(u+1,d,mu);
	dfs(u+1,d*p[u],-mu);
}

int main(){
//	freopen("3.in","r",stdin);
//	freopen("3.out","w",stdout);
	int T;
	h[0] = h[1] = 1;
	for(int i=2;i<maxn;i++) h[i] = 1ll * (mod - mod / i) * h[mod % i] % mod;
	for(int i=2;i<maxn;i++) h[i] = (h[i] + h[i-1]) % mod;
	for(scanf("%d",&T);T--;){
		scanf("%d",&n);int x = n;
		if(n == 2){
			puts("499122177");
			continue;
		}
		cnt = 0;
		for(int i=2;i*i<=x;i++) if(x % i == 0){
			p[++cnt] = i , c[cnt] = 0;
			for(;x % i == 0;x /= i)
				c[cnt] ++;
		}
		if(x > 1) p[++cnt] = x , c[cnt] = 1;
		dfs(1,1,1);
		printf("%d\n",(ans*1ll*Pow(n,mod-2)%mod+iv2+mod)%mod);
		ans = 0;
	}
}

H - Integral Calculus

在这里插入图片描述

仔细的抄式子,那么这就是一个任意模数多项式求逆的板题。
注意不知道为什么我抄出来答案要 × 4 \times 4

#include<bits/stdc++.h>
#define maxn 1100005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define db double
#define Ct const
#define Pi 3.1415926535897932384626433832795
using namespace std;

const int mod = 1000000009;

struct cp{
	db r,i;
	cp (Ct db &r=0,Ct db &i=0):r(r),i(i){}
	cp operator +(Ct cp &B)Ct{ return cp(r + B.r , i + B.i); }
	cp operator -(Ct cp &B)Ct{ return cp(r - B.r , i - B.i); }
	cp operator *(Ct cp &B)Ct{ return cp(r * B.r - i * B.i , i * B.r + r * B.i); }
	cp operator /(Ct db &B)Ct{ return cp(r / B , i / B); }
	cp conj()Ct{ return cp(r,-i); } 
}w[maxn];

int Wl,Wl2,lg[maxn];
void init(int n){
	for(Wl=1;n>=Wl<<1;Wl<<=1);Wl2 = Wl<<1;
	rep(i,0,Wl) w[i+Wl] = cp(cos(Pi*i/Wl) , sin(Pi*i/Wl));
	per(i,Wl-1,1) w[i] = w[i<<1];
	rep(i,2,Wl2) lg[i] = lg[i>>1]+1;
}
void FFT(cp *A,int n,int tp){
	static int r[maxn] = {};
	if(tp ^ 1) reverse(A+1,A+n);
	rep(i,0,n-1) i < (r[i] = r[i>>1] >> 1 | (i&1) << lg[n] - 1) && (swap(A[i],A[r[i]]) , 0);
	cp t;
	for(int L=1;L<n;L<<=1) for(int s=0,L2=L<<1;s<n;s+=L2) for(int k=s,x=L;k<s+L;k++,x++)
		t = w[x] * A[k+L] , A[k+L] = A[k] - t , A[k] = A[k] + t;
	if(tp ^ 1) rep(i,0,n-1) A[i] = A[i] / n;
}
void Mul(int *A,int *B,int *C,int n,int m,int cut = maxn,int mod = 1000000009){
	static int M = 32767; // 2 ^ 15 - 1
	static cp s[4][maxn];
	int L = 1 << lg[n + m] + 1;
	rep(i,0,L-1) 
		s[0][i] = cp(i <= n ? A[i] >> 15 : 0 , i <= m ? B[i] >> 15 : 0) ,
		s[1][i] = cp(i <= n ? A[i] & M : 0  , i <= m ? B[i] & M : 0);
	FFT(s[0],L,1) , FFT(s[1],L,1);
	rep(i,0,L-1){
		int v = (L-i) & (L-1);
		cp a[4] = {s[0][i] , s[0][v].conj() , s[1][i] , s[1][v].conj()};
		cp b[4] = {(a[0] + a[1]) * cp(0.5,0) , (a[1] - a[0]) * cp(0,0.5) , 
			(a[2] + a[3]) * cp(0.5,0) , (a[3] - a[2]) * cp(0,0.5)};
		s[2][i] = b[0] * b[1] + cp(0,1) * b[0] * b[3] , s[3][i] = b[2] * b[1] + cp(0,1) * b[2] * b[3];
	}	
	FFT(s[2],L,-1) , FFT(s[3],L,-1);
	rep(i,0,min(n+m,cut))
		C[i] = (
			(llround(s[2][i].r) % mod << 30)  
			+ ((llround(s[2][i].i) + llround(s[3][i].r)) % mod << 15)
			+ llround(s[3][i].i) ) % mod;
}

int Pow(int b,int k,int mod = 1000000009){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1)r=1ll*r*b%mod;return r; }
void Inv(int *A,int *B,int n,int mod = 1000000009){
	B[B[1] = 0] = Pow(A[0] , mod-2);
	static int t[maxn],t2[maxn];
	for(int k=2,L=4;k<(n<<1);k<<=1,L<<=1){
		rep(i,0,L-1) t[i] = i < k ? A[i] : B[i] = 0;
		Mul(t,B,t2,k-1,k-1,k-1);
		rep(i,0,L-1) t2[i] = i < k ? 2 * (i == 0) - t2[i] : 0;
		Mul(t2,B,B,k-1,k-1,min(k-1,n-1));
	}
}

int n = 200001 , fac[maxn] , inv[maxn] , invf[maxn] , A[maxn] , B[maxn] , C[maxn] , D[maxn];

int main(){
	init(n << 1);
	fac[0] = fac[1] = inv[0] = inv[1] = invf[0] = invf[1] = 1;
	rep(i,2,n << 1 | 1) fac[i] = 1ll * fac[i-1] * i % mod , inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod,
		invf[i] = 1ll * invf[i-1] * inv[i] % mod;
	rep(i,1,n-1) 
		A[i] = invf[2 * i];
	rep(i,0,n-1)
		B[i] = invf[2 * i + 1];
	Inv(B,C,n);
	Mul(A,C,B,n-1,n-1,n-1);
	rep(i,1,n-1)
		B[i] = (i&1 ? 1ll : -1ll) * B[i] * Pow(2,2*i) % mod * Pow(Pow(2,2*i) - 1 , mod-2) % mod * fac[2 * i - 1] % mod;
	int T;
	for(scanf("%d",&T);T--;){
		scanf("%d",&n);
		printf("%d\n",(4ll * B[2*n] * Pow(B[n] , mod-3) % mod + mod) % mod);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/107497985