zoukankan      html  css  js  c++  java
  • hdu 6053 TrickGCD 筛法

    TrickGCD

    Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)


    Problem Description
    You are given an array A , and Zhu wants to know there are how many different array B satisfy the following conditions?

    1BiAi
    * For each pair( l , r ) (1lrn) , gcd(bl,bl+1...br)2
     
    Input
    The first line is an integer T(1T10) describe the number of test cases.

    Each test case begins with an integer number n describe the size of array A.

    Then a line contains n numbers describe each element of A

    You can assume that 1n,Ai105
     
    Output
    For the kth test case , first output "Case #k: " , then output an integer as answer in a single line . because the answer may be large , so you are only need to output answer mod 109+7
     
    Sample Input
    1 4 4 4 4 4
     
    Sample Output
    Case #1: 17
     
    Source
     
    Recommend
    liuyiding
    题意:给你n个数字,每个位置的数字可以小于等于a[i],求所有gcd(l,r)都满足大于等于2的情况数;
    思路:显然枚举gcd的情况,对于每个位置都有a[i]/gcd的个数可以满足条件,gcd的情况的所有a[i]/gcd的乘积;
       这个也需要优化,枚举除数,a[i]/gcd相同的为一块,nlong(n)的复杂度*快速幂的log,后面的用容斥筛一下就好了;
       莫比乌斯好像也可以。
     
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    #include<bitset>
    #include<time.h>
    using namespace std;
    #define LL long long
    #define pi (4*atan(1.0))
    #define eps 1e-4
    #define bug(x)  cout<<"bug"<<x<<endl;
    const int N=1e5+10,M=1e6+10,inf=1e9+7,MOD=1e9+7;
    const LL INF=1e18+10,mod=1e9+7;
    
    int a[N],sum[N];
    LL dp[N],num[N];
    LL qpow(LL a,LL b,LL c)
    {
        LL ans=1;
        while(b)
        {
            if(b%2)ans=(ans*a)%c;
            b>>=1;
            a=(a*a)%mod;
        }
        return ans;
    }
    int main()
    {
        int n;
        int T,cas=1;
        scanf("%d",&T);
        while(T--)
        {
            memset(a,0,sizeof(a));
            memset(sum,0,sizeof(sum));
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
            {
                int x;
                scanf("%d",&x);
                a[x]++;
            }
            for(int i=1;i<=100005;i++)
                sum[i]=sum[i-1]+a[i];
            for(int i=2;i<=100000;i++)//枚举除数
            {
                num[i]=1LL;
                for(int j=0;j<=100000;j+=i)
                {
                    int b;
                    if(j+i-1>100000)b=sum[100001]-sum[j-1];
                    else if(j==0) b=sum[j+i-1];
                    else b=sum[j+i-1]-sum[j-1];
                    int a=j/i;
                    if(a==0&&b)num[i]=0;
                    else if(b)num[i]=(num[i]*qpow(a,b,mod))%mod;
                }
            }
            for(int i=100000;i>=2;i--)
            {
                dp[i]=num[i];
                for(int j=i+i;j<=100000;j+=i)
                    dp[i]-=dp[j],dp[i]=(dp[i]%mod+mod)%mod;
            }
            LL ans=0;
            for(int i=2;i<=100000;i++)
                ans+=dp[i],ans%=mod;
            printf("Case #%d: %lld
    ",cas++,ans);
    
        }
        return 0;
    }
  • 相关阅读:
    【转载】Unity 合理安排增量更新(热更新)
    COCOS2D 释放资源的最佳时机
    【转载】利用Unity自带的合图切割功能将合图切割成子图
    用GL画出人物的移动路径
    使用行为树(Behavior Tree)实现游戏AI
    C#学习笔记
    题目:给定一数组 例如:a = [1,2,3,5,2,1] 现用户提供一个数字 请返回用户所提供的数字的所有下标
    算法: 归并排序
    题目:给定两个有序数组,对其进行合并
    数据结构 顺序表实现优先队列 回顾练习
  • 原文地址:https://www.cnblogs.com/jhz033/p/7246028.html
Copyright © 2011-2022 走看看