LGP5616口胡

上个星期kds给我看的题,第一眼不会做,然后稍微想了一下还是秒了。

感觉还是太简单了。

考虑到值域只有 \(300\),我们这里假设 \(n\) 就是 \(300\)。重复的肯定开个桶记下来。

考虑经典结论:只会有至多一个质因子大于 \(17\)

根据这个根号分治,那么我们记录 \(2^{0\sim 8}\times 3^{0\sim 5}\times 5^{0\sim 3}\times 7^{0\sim 2}\times 11^{0\sim 2}\times 13^{0\sim 2}\times 17^{0\sim 2}\) 这些状态。

对这个部分我们做 lcm 卷积,由于每个初始的元素只会有至多一个质因子大于 \(17\)

考虑在每组元素的 lcm 处统计其可能的 lcm 之和,但是显然只能够在 lcm 的倍数处统计。

这个很简单,对权值做一个高维差分就行了。

而统计可能的 lcm 也非常简单。对于每个大于 \(17\) 的质因子开桶。因为质因子不同的部分互不相干所以可以写成类似下面这种形式:

\[\prod((2^{cnt_i}-1)\times pri_i+1)-1 \]

前面的 \(p,c\) 是不大于 \(17\) 的,后面的 \(pri,cnt\) 的大于 \(17\) 的。

于是接下来就很简单了。

复杂度大概是 \(O(17496\times 7\times\frac{n}{\ln n})\),这个显然随随便便跑过去吧。

好像还爆标了。目前是 rk1。

#include<cstdio>
#include<cctype>
namespace SOLVE{
	inline int read(){
		int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
	}
	const int H[]={1,1,9,54,216,648,1944,5832,17496},lim[]={1,9,6,4,3,3,3,3};
	int n,P,t[10][10],CB[305],w[17500],cnt[17500],F[17500][60];int top,pri[305],pos[305];
	struct Barrett{
		typedef unsigned long long ull;
		typedef __uint128_t LL;
		ull m,B;
		Barrett(const ull&m=2):m(m),B((LL(1)<<64)/m){}
		friend inline ull operator%(const ull&a,const Barrett&mod){
			ull r=a-mod.m*(LL(mod.B)*a>>64);return r>=mod.m?r-mod.m:r;
		}
	}mod;
	inline void sieve(const int&M){
		for(int i=2;i<=M;++i){
			if(!pos[i])pri[pos[i]=++top]=i;for(int x,j=1;j<=top&&(x=i*pri[j])<=M;++j)pos[x]=j;
		}
	}
	inline int pow(int a,int b=P-2){
		int ans(1);for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;return ans;
	}
	inline void main(){
		int ans(0);pri[0]=300;sieve(300);n=read();mod=Barrett(P=read());while(n--)++CB[read()];n=300;
		for(int i=0;i<=17495;++i)for(int k=0;k<=55;++k)F[i][k]=1;
		for(int c=1;c<=7;++c){t[c][0]=1;for(int k=1;k<=8;++k)t[c][k]=1ll*t[c][k-1]*pri[c]%mod;}
		for(int i=1;i<=n;++i){
			int sta(0),x=i;while(pri[pos[x]]<=17)sta+=H[pos[x]],x/=pri[pos[x]];CB[i]=pow(2,CB[i]);
			if(x==1)F[sta][0]=1ll*F[sta][0]*CB[i]%mod;else F[sta][pos[x]-7]=1ll*F[sta][pos[x]-7]*CB[i]%mod;
		}
		for(int c=1;c<=7;++c)for(int i=0;i<=17495;++i)if(i/H[c]%lim[c]){
			for(int k=0;k<=55;++k)F[i][k]=1ll*F[i][k]*F[i-H[c]][k]%mod;
		}
		for(int i=0;i<=17495;++i){
			w[i]=1;for(int k=0;k<=55;++k)w[i]=1ll*w[i]*(1ll*(F[i][k]-1)*(k?pri[k+7]:1)%mod+1)%mod;--w[i];
		}
		for(int c=1;c<=7;++c)for(int i=17495;i>=0;--i)if(i/H[c]%lim[c])w[i]=(1u*P+w[i]-w[i-H[c]])%mod;
		for(int c=1;c<=7;++c)for(int i=0;i<=17495;++i){
			if(i/H[c]%lim[c])cnt[i]=cnt[i-H[c]]+1;else cnt[i]=0;
			w[i]=1ll*w[i]*t[c][cnt[i]]%mod;
		}
		for(int i=0;i<=17495;++i)ans=(1u*ans+w[i])%mod;printf("%d",(ans+1)%mod);
	}
}
signed main(){
	SOLVE::main();
}
posted @ 2022-10-18 16:47  Prean  阅读(23)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};