• 2017 多校2 hdu 6053 TrickGCD


    2017 多校2 hdu 6053 TrickGCD

    题目:

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

    • (1≤B_i≤A_i)
    • For each pair((l , r) (1≤l≤r≤n) , gcd(bl,bl+1...br)≥2)

    Input

    The first line is an integer (T(1≤T≤10)) 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 (1≤n,A_i≤10^{5})

    Output

    For the (k)th 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 (10^{9}+7)

    思路:

    枚举(g = gcd(b_1,b_2,....,b_n)),
    那么(gcd为g)的倍数的答案就是(prod_{i=1}^{n}frac{A_i}{g})
    每次暴力计算是不行的,想到一个数在(g到2g-1)除以g结果是不变的
    所以可以预处理区间数字个数的前缀和,(O(nlogn))类似素数筛法预处理出每个(g)的答案
    现在要计算(gcd为g)的答案,我们从大到小枚举,同时更新它的约数的答案,就可以保证不重复了
    从小到大枚举过去就要用到莫比乌斯函数去计算了
    (令F(i)为gcd为i的倍数的方案数,f(i)为gcd为i的方案数)
    (F(i) = sum_{i|d}^{}{f(d)} ightarrow f(i) = sum_{i|d}u(frac{d}{i})F(d))
    代码贴的是比赛时过的姿势

    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> P;
    typedef long long LL;
    const int mod = 1e9 + 7;
    const int N = 1e5 + 10;
    vector<int> v[N];
    int n;
    int sum[N],ans[N];
    void init(){
        for(int i = 2;i < N;i++){
            for(int j = i;j < N;j+=i) v[j].push_back(i);
        }
    }
    int qpow(int x,int y){
        int ans = 1;
        while(y){
            if(y&1) ans = 1LL* ans * x % mod;
            x = 1LL * x * x % mod;
            y >>= 1;
        }
        return ans;
    }
    int main(void)
    {
        init();
        int T, x;
        int cas = 1;
        cin>>T;
        while(T--){
            memset(sum, 0, sizeof(sum));
            scanf("%d",&n);
            int mi = N;
            for(int i = 1;i <= n;i++) {
                scanf("%d",&x);
                mi = min(x,mi);
                sum[x]++;
            }
            for(int i = 1;i < N;i++) sum[i]+=sum[i-1];
            for(int i = 2;i <= mi;i++){
                ans[i] = 1;
                for(int j = i;j < N;j+=i){
                    int l = j + i - 1 > N - 1?N-1:j + i - 1;
                    ans[i] = 1LL * ans[i] * qpow(j / i,sum[l] - sum[j - 1]) % mod;
                }
            }
            int res = 0;
            for(int i = mi;i >= 2;i--){
                res = (res + ans[i])%mod;
                for(int j = 0;j < v[i].size();j++) ans[v[i][j]] = (ans[v[i][j]] - ans[i] + mod)%mod;
            }
            printf("Case #%d: %d
    ",cas++,res);
        }
        return 0;
    }
    
  • 相关阅读:
    你可能不知道的 30 个 Python 语言的特点技巧
    正则替换sql为动态sql
    列表按指定个数分割后格式化输出
    多线程队列下载天涯帖子
    多线程下载图片
    sublime text3 运行python配置
    01_什么是接口测试
    02_Fiddler使用
    01_Fiddler安装
    05_功能测试
  • 原文地址:https://www.cnblogs.com/jiachinzhao/p/7267453.html
Copyright © 2020-2023  润新知