LGP5616口胡

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

感觉还是太简单了。

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

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

根据这个根号分治,那么我们记录 208×305×503×702×1102×1302×1702 这些状态。

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

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

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

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

((2cnti1)×prii+1)1

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

于是接下来就很简单了。

复杂度大概是 O(17496×7×nlnn),这个显然随随便便跑过去吧。

好像还爆标了。目前是 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();
}

本文作者:Prean

本文链接:https://www.cnblogs.com/lmpp/p/16803183.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Prean  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
var canShowAdsense=function(){return !!0};
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起