AtCoder Regular Contest 116C - Multiple Sequences

https://atcoder.jp/contests/arc116/tasks/arc116_c

经典不会组合

这题关键是想到对于dp[n][pi^ki],方案数是c(n-1+ki,n-1),就是你从(1,1)走到(n,ki)有多少种走法,而且可以连续增加ki,就相当于一次乘以pi的多次幂

然后线性筛预处理一下最小质因子,每次把最小质因数分解一下,然后递推就行了

也可以线性筛的时候记录一下最小质因子的幂次然后直接O(m)做,但还是O(mlogm)好写

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=4e5+10;
const int mod=998244353;

int n,m;ll ans;
int p[maxl],dy[maxl];
ll fac[maxl],inv[maxl],dp[maxl];
bool no[maxl];

inline void shai()
{
	for(int i=2;i<maxl;i++)
	{
		if(!no[i]) p[++p[0]]=i,dy[i]=i;
		int j=1,t=p[1]*i;
		while(j<=p[0] && t<maxl)
		{
			no[t]=true;dy[t]=p[j];
			if(i%p[j]==0)
				break;
			t=p[++j]*i;
		}
	}
}

inline ll qp(ll a,ll b)
{
	ll ans=1,cnt=a;
	while(b)
	{
		if(b&1) ans=ans*cnt%mod;
		cnt=cnt*cnt%mod;
		b>>=1;
	}
	return ans;
}
inline void prework()
{
	shai();
	fac[0]=1;
	for(int i=1;i<maxl;i++)
		fac[i]=fac[i-1]*i%mod;
	inv[maxl-1]=qp(fac[maxl-1],mod-2);
	for(int i=maxl-2;i>=0;i--)
		inv[i]=inv[i+1]*(i+1)%mod;
	scanf("%d%d",&n,&m);
}


inline ll c(int n,int r)
{
	if(r>n || r<0) return 0;
	return fac[n]*inv[n-r]%mod*inv[r]%mod;
}
inline void add(ll &a,ll b){a=(a+b)%mod;}

inline void mainwork()
{
	dp[1]=1;ans=1;
	for(int i=2;i<=m;i++)
	{
		int x=i,d=dy[i],cnt=0;
		while(x%d==0 && x>1)
			cnt++,x/=d;
		dp[i]=dp[x]*c(cnt+n-1,n-1)%mod;
		add(ans,dp[i]);
	}
}

inline void print()
{
	printf("%lld\n",ans);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

 

上一篇:Angular input decorator学习笔记


下一篇:Commonsense Causal Reasoning between Short Texts