首页 > 其他 > 详细

[BZOJ4305] 数列的GCD

时间:2019-06-20 20:39:04      阅读:206      评论:0      收藏:0      [点我收藏+]

[BZOJ4305] 数列的GCD

题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=4305

Solution

\(a_i\)表示\(d=i\)时的答案,恰好\(k\)个不同也就是恰好\(n-k\)个相同,设\(s=n-k\)

设有\(c\)个题目给出来数是的\(i\)的倍数,则可以得到\(a_i\)的表达式:
\[ a_i=\binom{c}{s}\cdot (\lfloor\frac{m}{i}\rfloor-1)^{c-s}\cdot \lfloor\frac{m}{i}\rfloor^{n-c}-\sum_{j=2}^{m/i}a_{ij} \]
我们发现前面的部分算到了\(\gcd\)\(i\)的倍数的情况,所以在后面减掉。

利用调和级数,复杂度为\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
 
void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
  
void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}
 
#define lf double
#define ll long long 
 
#define pii pair<int,int >
#define vec vector<int >
 
#define pb push_back
#define mp make_pair
#define fr first
#define sc second
 
#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 
 
const int maxn = 3e5+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7;
 
int a[maxn],t[maxn],n,m,k,b[maxn],fac[maxn],ifac[maxn],inv[maxn];
 
int qpow(int a,int x) {
    int res=1;
    for(;x;x>>=1,a=1ll*a*a%mod) if(x&1) res=1ll*res*a%mod;
    return res;
}
 
void prepare(int l) {
    inv[0]=inv[1]=fac[0]=ifac[0]=1;
    FOR(i,1,l) fac[i]=1ll*fac[i-1]*i%mod;
    FOR(i,2,l) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    FOR(i,1,l) ifac[i]=1ll*ifac[i-1]*inv[i]%mod;
}
 
int c(int x,int y) {return 1ll*fac[x]*ifac[y]%mod*ifac[x-y]%mod;}
 
int main() {
    read(n),read(m),read(k);for(int i=1,x;i<=n;i++) read(x),b[x]++;k=n-k;
    prepare(max(m,n));
    for(int i=1;i<=m;i++)
        for(int j=i;j<=m;j+=i) t[i]+=b[j];
    for(int i=m;i;i--) {
        if(t[i]<k) continue;
        a[i]=1ll*c(t[i],k)*qpow(m/i-1,t[i]-k)%mod*qpow(m/i,n-t[i])%mod;
        for(int j=i<<1;j<=m;j+=i) a[i]=(a[i]-a[j])%mod;
    }
    for(int i=1;i<=m;i++) printf("%d ",(a[i]+mod)%mod);puts("");
    return 0;
}

[BZOJ4305] 数列的GCD

原文:https://www.cnblogs.com/hbyer/p/11061104.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!