题解 P5216 【DLS 采花】

题解:

考虑算每个数对答案的贡献。

第i个数的有贡献,当且仅当第i个数的约数出现在它后面。

假设第i个数有x个约数,那么有贡献的概率就是,有贡献的方案数就是总方案数概率。

为什么是呢?有个数,要选出那个数放在最前面,当然是

代码:

#include<bits/stdc++.h>
using namespace std;
#define next Next
#define last Last
#define int long long
const int N=1e6+5;
const int mod=998244353;
int n,ans,a[N],b[N],gs[N];
/*char buf[1<<21],*p1=buf,*p2=buf;
inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}*/
#define gc getchar
inline int read()
{
    int ret=0,f=0;char c=gc();
    while(!isdigit(c)){if(c=='-')f=1;c=gc();}
    while(isdigit(c)){ret=ret*10+c-48;c=gc();}
    if(f)return -ret;return ret;
}
int kuai(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)res=res*a%mod;
        b=b/2;
        a=a*a%mod;
    }
    return res;
}
signed main()
{
    n=read();
    int jc=1;
    for(int i=1;i<=n;i++)jc=jc*i%mod;
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        b[a[i]]++;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j*j<=a[i];j++)
            if(a[i]%j==0)
            {
                gs[i]+=b[j];
                if(j*j!=a[i])gs[i]+=b[a[i]/j];
            }
        ans=(ans+jc*kuai(gs[i],mod-2)%mod*a[i]%mod)%mod;
    }
    cout<<ans;
}