第十届中国大学生程序设计竞赛 重庆站(CCPC 2024 Chongqing Site)

A. 乘积,欧拉函数,求和

注意到 ,只要 个质数,直接状压有没有选这些质数。每个数除掉掉这 个质数,剩下一个大质数或 ,把剩下的数相同的一起做,一起乘 .

int n,a[maxn],ans;
int pre[15]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
inline int ksm(int a,int b=mod-2){
	int ans=1;
	while(b){
		if(b&1)ans=ans*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ans;
}
vector<int> id[maxn];
int dp[1<<15],f[1<<15];
int msk[maxn];
void work(){
	n=read();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=1;i<=n;i++){
		int x=a[i];
		for(int j=0;j<15;j++)if(x%pre[j]==0){
			msk[i]|=1<<j;
			while(x%pre[j]==0)x/=pre[j];
		}
		if(x==53*53)x=53;
		id[x].pb(i);
	}
	dp[0]=1;
	for(int i=1;i<=maxn-10;i++)if(id[i].size()){
		mems(f,0);
		for(int j:id[i]){
			for(int s=(1<<15)-1;~s;s--){
				(f[s|msk[j]]+=dp[s]*(i==1?a[j]:a[j]/i*(i-1))+f[s]*a[j])%=mod;
			}
		}
		for(int s=0;s<(1<<15);s++)(dp[s]+=f[s])%=mod;
	}
	for(int s=0;s<(1<<15);s++)if(dp[s]){
		int val=dp[s];
		for(int i=0;i<15;i++)if(s&(1<<i))val=val*ksm(pre[i])%mod*(pre[i]-1)%mod;
		(ans+=val)%=mod;
	}
	printf("%lld\n",ans);
}

B. osu!mania

模拟, 下取整。

C. 连方

特判全 . 或全 #,剩下的一定可以构造出来。 反过来填,使第一行连通。 取一个单点连接第 行, 行同 行,第 行将第 行的单点连通。

D. 有限小数

因子拆出来,令 中没有 因子。发现 。枚举 ,有 。exgcd 解

int a,b;
pii ans={inf,inf};
void exgcd(int a,int b,int &x,int &y){
	if(!b){x=1,y=0;return ;}
	exgcd(b,a%b,x,y);
	int p=x;
	x=y,y=p-(a/b)*y;
}
void work(){
	a=read(),b=read();ans={inf,inf};int p=1;
	while(b%2==0)b/=2,p*=2;
	while(b%5==0)b/=5,p*=5;
	int xx=0,yy=0;exgcd(b,p,xx,yy);
	if(b==1){puts("0 1");return ;}
	for(int i=1;i*b<=inf;i*=2){
		for(int j=i;j*b<=inf;j*=5){
			int q=j,c=yy,d=q*b;
			c*=-a*q;c%=b,c+=b,c%=b;
			ans=min(ans,{c,d});
		}
	}
	printf("%lld %lld\n",ans.fi,ans.se);
}

E. 合成大西瓜

可以取到所有度数 的点和次大值。

H. str(list(s))

表示第 轮模 的位置的和, 表示第 轮模 的位置是否为 ' ‘的方案数。按规则模拟。

I. 算术

J. 骰子

答案为 。在一个 的矩阵内可以从以 为底去到相邻位置以 为底。

K. 小 C 的神秘图形

模拟。

M. Median Replacement

如果一个数成为长为 的区间的中位数,就可以成为最后的数。将值域离散化,对于 计算答案 的方案数,即 减去答案 的方案数。转为 ,设 表示这个和上一个是否 ,不能存在 。很难发现 是关于 的若干次多项式,取 个之后插值。

int n,ans;
int l[maxn],r[maxn];
int lsh[maxn],len;
int x[maxn],y[maxn];
int dp[maxn][2][2];
int calc(int v){
	for(int i=1;i<=n;i++)dp[i][0][0]=dp[i][0][1]=dp[i][1][0]=0;dp[0][0][0]=1;
	int mul=1;
	for(int i=1;i<=n;i++){
		int len=r[i]-l[i]+1,l1=max(0ll,min(len,v-l[i])),l2=max(0ll,min(len,r[i]-v+1));
		dp[i][0][0]=(dp[i-1][0][0]+dp[i-1][1][0])*l1%mod;
		dp[i][0][1]=dp[i-1][0][0]*l2%mod;
		dp[i][1][0]=dp[i-1][0][1]*l1%mod;
		mul=mul*len%mod;
	}
	return (mul+3*mod-dp[n][0][0]-dp[n][0][1]-dp[n][1][0])%mod;
}
int lag(int k,int v){
	int res=0;
	for(int i=1;i<=k;i++){
		int mul1=1,mul2=1;
		for(int j=1;j<=k;j++)if(i!=j){
			mul1=mul1*(v+mod-x[j])%mod;
			mul2=mul2*(x[i]+mod-x[j])%mod;
		}
		(res+=y[i]*mul1%mod*ksm(mul2))%=mod;
	}
	return res;
}
void work(){
	n=read();ans=0;
	for(int i=1;i<=n;i++)l[i]=read();
	for(int i=1;i<=n;i++)r[i]=read();
	lsh[len=1]=1;
	for(int i=1;i<=n;i++)lsh[++len]=l[i],lsh[++len]=r[i]+1;
	sort(lsh+1,lsh+len+1),len=unique(lsh+1,lsh+len+1)-lsh-1;
	for(int i=1;i<len;i++){
		int ll=lsh[i],rr=lsh[i+1]-1,k=min(rr-ll+1,200ll);
		for(int j=ll;j<=ll+k-1;j++)y[j-ll+1]=calc(x[j-ll+1]=j);
		for(int j=1;j<=k;j++)(y[j]+=y[j-1])%=mod;
		if(rr-ll+1==k)(ans+=y[rr-ll+1])%=mod;
		else (ans+=lag(k,rr))%=mod;
	}
	printf("%lld\n",ans);
}