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();
}