qoj #8147. Math Exam

qoj #8147. Math Exam

考虑 \(4a_1 = a_1^2 + 2a_1 + 1\),解得 \(a_1 = 1\)。

接下来考虑 \(4a_i = a_i^2 + 2a_i + 1 - a_{i-1}^2 - 2a_{i-1} - 1\)。

我们可以解得 \((a_{i-1}+1)^2 = (a_i - 1)^2\),则有两种情况:

  • \(a_i = a_{i-1} + 2\)

  • \(a_i = - a_{i-1}\)

我们令 \(b_i = \dfrac{|a_i + 1|}{2}\),显然 \(b_1 = 1\)。

接下来我们声称 \(b_i = b_{i-1} - 1\) 或 \(b_i = b_{i+1} + 1\)。

同时,因为 \(a_i \in [-m,m]\),得 \(b_i \in [0,\dfrac{m+1}{2}]\)。

通过计算发现,\(b\) 数组与 \(a\) 数组一一对应。

接下来对 \(b\) 计数,使用反射容斥即可。

//Ad astra per aspera
#include<iostream>
#include<cstdio>
using namespace std;
const long long mod=998244353;
long long inv(long long num){
	long long pre=mod-2,ans=1;
	while(pre){
		if(pre&1){
			ans=ans*num%mod;
		}
		num=num*num%mod;
		pre>>=1;
	}
	return ans;
}
long long fact[10000010],invfact[10000010],sum_C[10000010];
int n,m;
void init(){
	fact[0]=invfact[0]=1;
	for(int i=1;i<=n;i++){
		fact[i]=fact[i-1]*i%mod;
		invfact[i]=invfact[i-1]*fact[i]%mod;
	}
	long long tmp=inv(invfact[n]);
	for(int i=n;i>=1;i--){
		invfact[i]=tmp*invfact[i-1]%mod;
		tmp=tmp*fact[i]%mod;
	}
	for(int i=0;i<=n;i++){
		sum_C[i]=invfact[i]*invfact[n-i]%mod*fact[n]%mod;
	}
	for(int i=1;i<=n;i++){
		sum_C[i]=(sum_C[i-1]+sum_C[i])%mod; 
	}
}
long long sumC(int l,int r){
	long long ans=sum_C[r];
	if(l) ans=((ans-sum_C[l-1])%mod+mod)%mod;
	return ans;
}
int mod_2(int num){
	if(num%2==0){
		return 0;
	}
	else{
		return 1;
	}
}
long long query(int l,int r){
	if(n%2==0){
		if(mod_2(l)==0){
			l++;
		}
		if(mod_2(r)==0){
			r--;
		}
	}
	else{
		if(mod_2(l)==1){
			l++;
		}
		if(mod_2(r)==1){
			r--;
		}
	}
	if(r>=1+n){
		r=min(r,1+n);
	}
	if(l<=1-n){
		l=max(l,1-n);
	}
	int new_l=(n+l-1)/2,new_r=(n+r-1)/2;
	return sumC(new_l,new_r);
}
long long query1(int l,int r){
	int L=l,R=r;
	long long ans=0;
	bool flag=true;
	while(true){
		int new_L=(L-1)*2-R,new_R=(L-1)*2-L;
		L=new_L;
		R=new_R;
		if(R<1-n){
			break;
		}
		long long pre=query(L,R);
		if(flag==true){
			ans+=pre;
			ans%=mod;
		}
		else{
			ans-=pre;
			ans%=mod;
		}
		flag=!flag;
	}
	return (ans%mod+mod)%mod;
}
long long query2(int l,int r){
	int L=l,R=r;
	long long ans=0;
	bool flag=true;
	while(true){
		int new_L=(R+1)*2-R,new_R=(R+1)*2-L;
		L=new_L;
		R=new_R;
		if(L>1+n){
			break;
		}
		long long pre=query(L,R);
		if(flag==true){
			ans+=pre;
			ans%=mod;
		}
		else{
			ans-=pre;
			ans%=mod;
		}
		flag=!flag;
	}
	return (ans%mod+mod)%mod;
}
int main(){
	scanf("%d %d",&n,&m);
	n--; 
	init();
	int l_m=0,r_m=(m+1)/2;
	long long ans=query(l_m,r_m);
	ans-=query1(l_m,r_m);
	ans-=query2(l_m,r_m);
	printf("%lld",(ans%mod+mod)%mod);
	return 0;
}
posted @ 2026-03-27 23:31  Oken喵~  阅读(15)  评论(0)    收藏  举报