zoukankan      html  css  js  c++  java
  • SCUT

    https://scut.online/p/157

    鉴于多年(都没几个月)搞数论的经验,这种时候枚举g肯定是对的。

    那么肯定是要莫比乌斯函数作为因子,因为很显然?

    但是为什么要搞个负的呢?其实是因为这个题目的g1的时候并不都是合法的,反而是g2的时候都是合法的,所以g==6的时候才是重复的。

    然后考虑怎么统计他们的倍数。

    每次都因数分解,是很慢的。

    考虑到这题的特征,数字特别小。用个cnt把每个数字都数一数。

    然后从小的数字开始把它所有的倍数都加在它身上。

    最后预处理一波组合数就可以了。

    整体复杂度每次是(O(nlogn))的,比(O(nsqrt{n}))快了近10倍。

    不过最后还是快读最快啊233!

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXN=1e5;
    
    int pri[MAXN+5];
    int &pritop=pri[0];
    int mu[MAXN+5];
    void sieve(int n=MAXN) {
        mu[1]=1;
        for(int i=2; i<=n; i++) {
            if(!pri[i]) {
                pri[++pritop]=i;
                mu[i]=-1;
            }
            for(int j=1; j<=pritop; j++) {
                int &p=pri[j];
                int t=i*p;
                if(t>n)
                    break;
                pri[t]=1;
                if(i%p) {
                    mu[t]=-mu[i];
                } else {
                    mu[t]=0;
                    break;
                }
            }
        }
    }
    
    const int mod=1e9+7;
    
    int inv[MAXN+5],fac[MAXN+5],invfac[MAXN+5];
    
    void init_fac_invfac(int n=MAXN) {
        inv[1]=1;
        for(int i=2; i<=n; i++)
            inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
        fac[0]=1,invfac[0]=1;
        for(int i=1; i<=n; i++) {
            fac[i]=1ll*fac[i-1]*i%mod;
            invfac[i]=1ll*invfac[i-1]*inv[i]%mod;
        }
    }
    
    inline ll C(ll n,ll m) {
        if(n<m)
            return 0;
        return 1ll*fac[n]*invfac[n-m]%mod*invfac[m]%mod;
    }
    
    inline int read(){
        int x=0;
        char c=getchar();
        while(c<'0'||c>'9')
            c=getchar();
        do{
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }while(c>='0'&&c<='9');
        return x;
    }
    
    inline void write(int x){
        if(x>9){
            write(x/10);
        }
        putchar(x%10+'0');
        return;
    }
    
    int cnt[MAXN+5];
    int main() {
    #ifdef Yinku
        freopen("Yinku.in","r",stdin);
    #endif // Yinku
        sieve();
        init_fac_invfac();
        int n,m;
        while(~scanf("%d%d",&n,&m)) {
            memset(cnt,0,sizeof(cnt));
            for(int i=1; i<=n; i++) {
                int tmp=read();
                cnt[tmp]++;
            }
            for(int d=2;d<=100000;d++){
                for(int td=d+d;td<=100000;td+=d)
                    cnt[d]+=cnt[td];
            }
            ll sum=0;
            for(int d=2; d<=100000; d++) {
                if(mu[d]==0||cnt[d]<m)
                    continue;
                ll tmp=(-mu[d])*C(cnt[d],m);
                if(tmp>=mod||tmp<=-mod) {
                    tmp%=mod;
                }
                if(tmp<0)
                    tmp+=mod;
                sum+=tmp;
                if(sum>=mod)
                    sum-=mod;
            }
            write((int)sum);
            puts("");
        }
    }
    
  • 相关阅读:
    数据库的架构和优化
    描述一个高性能高可靠的网站架构——如何设计一个秒杀系统
    PHP手册-函数参考-加密扩展
    系统性能指标总结
    PHP实现负载均衡的加权轮询
    PHP生成二维码
    高性能网站架构
    PHP实现Redis的数据结构和LFU/LRU
    缓存的设计及PHP实现LFU
    网络开发库从libuv说到epoll
  • 原文地址:https://www.cnblogs.com/Yinku/p/11025889.html
Copyright © 2011-2022 走看看