zoukankan      html  css  js  c++  java
  • HDU 6053 TrickGCD(分块)

    【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6053

    【题目大意】

      给出一个数列每个位置可以取到的最大值,
      问这个可以构造多少个数列,使得他们的最大公约数大于1

    【题解】

      我们可以枚举最大公约数k,对于k来说,
      他对答案的贡献为∏[ai/k],我们将数列中的数字转化为权值数组
      ∏_{i=1}^{100000}[i/k],对于求解i/k的部分我们可以进行数值分块,
      j*k-1~j*k+k-1的数值除k得到的结果都是相同的,因此可以直接求这个结果的幂次,
      这时候只要再加一个权值数组的前缀和,问题就迎刃而解了。
      数值分块计算的复杂度为n+n/2+n/3+n/4+n/5+……+n/n=nlogn。
      对于计算结果,我们需要进行容斥,奇数次素数乘的系数为1,偶数次素数乘的系数为-1,
      对于出现素数幂的合数其系数为0,
      我们发现这个容斥恰好是莫比乌斯函数的相反数,因此我们取反即可。
      这有个小小的优化,对于系数为0的情况,我们可以直接跳过,不进行计算。

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N=200010;
    typedef long long LL;
    const LL mod=1000000007;
    int T,n,a[N],b[N],cnt[N],cas=1,p[N]; 
    LL ans=0;
    int tot,miu[N],sum[N],v[N];
    void read(int&a){
        char ch;while(!((ch=getchar())>='0')&&(ch<='9'));
        a=ch-'0';while(((ch=getchar())>='0')&&(ch<='9'))a*=10,a+=ch-'0';
    }
    void mobius(int n){
        int i,j;
        for(miu[1]=1,i=2;i<=n;i++){
            if(!v[i])p[tot++]=i,miu[i]=-1;
            for(j=0;j<tot&&i*p[j]<=n;j++){
                v[i*p[j]]=1;
                if(i%p[j])miu[i*p[j]]=-miu[i];else break;
            }
        }for(i=1;i<n;i++)sum[i]=sum[i-1]+miu[i];
    }
    LL pow(LL a,LL b,LL p){if(b==0)return 1;LL t=1;for(a%=p;b;b>>=1LL,a=a*a%p)if(b&1LL)t=t*a%p;return t;}
    int main(){
        read(T);
        mobius(100000);
        while(T--){
            read(n);
            ans=0; int mn=~0U>>1,mx=0;
            memset(cnt,0,sizeof(cnt));
            for(int i=1;i<=n;i++)read(a[i]),mn=min(a[i],mn),mx=max(a[i],mx),cnt[a[i]]++;
            for(int i=1;i<=200000;i++)cnt[i]+=cnt[i-1]; 
            for(int i=2;i<=mn;i++){
                if(!miu[i])continue;
                LL tmp=1; 
                for(int j=1;i*j<=100000;j++)tmp=tmp*pow(j,cnt[i*j+i-1]-cnt[i*j-1],mod)%mod;
                // j<=100000/i -> i*j<=100000 : TLE -> AC
                ans=(ans-tmp*miu[i]+mod)%mod;
            }printf("Case #%d: %lld
    ",cas++,ans);
        }return 0;
    }
  • 相关阅读:
    Django forms组件
    Django 分页器
    Django Ajax
    Django 多表操作2
    js12种应该注意的地方
    Web自动化测试python环境中安装 --selenium安装、火狐和火狐驱动版本、谷歌和谷歌驱动版本、测试
    python学习-文件操作
    关于redis搭建环境
    扩展知识
    javascript之Banner图片焦点轮播
  • 原文地址:https://www.cnblogs.com/forever97/p/hdu6053.html
Copyright © 2011-2022 走看看