• HDU 6053 TrickGCD(莫比乌斯反演)


    http://acm.hdu.edu.cn/showproblem.php?pid=6053

    题意:
    给出一个A数组,B数组满足Bi<=Ai。

    现在要使得这个B数组的GCD值>=2,求共有多少种情况。

    思路:
    在比赛的时候筛了素数表,然后枚举GCD来做,但是还是有些重复情况无办法剔除,赛后才知道是要用莫比乌斯来处理的,然后就趁机学习了一下莫比乌斯。

    先是枚举GCD,每个数的可选情况就是GCD/a【i】,在这里我们可以把GCD/a【i】相同的数一起处理,也就是用快速幂来计算,这样会显得更快。

    那么莫比乌斯是用来干嘛的呢?

    然后就是容斥思想。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<sstream>
      6 #include<vector>
      7 #include<stack>
      8 #include<queue>
      9 #include<cmath>
     10 #include<map>
     11 #include<set>
     12 using namespace std;
     13 typedef long long ll;
     14 typedef pair<int,int> pll;
     15 const int INF = 0x3f3f3f3f;
     16 const int maxn = 1e5 + 5;
     17 
     18 const int mod= 1e9+7;
     19 
     20 int n;
     21 int a[maxn];
     22 
     23 ll cnt[maxn];
     24 ll num[3*maxn];
     25 
     26 bool check[maxn+1000];
     27 int prime[maxn+1000];
     28 int mu[maxn+1000];
     29 
     30 void Moblus()
     31 {
     32     memset(check,false,sizeof(check));
     33     mu[1] = 1;
     34     int tot = 0;
     35     for(int i = 2; i <= maxn; i++)
     36     {
     37         if( !check[i] ){
     38             prime[tot++] = i;
     39             mu[i] = -1;
     40         }
     41         for(int j = 0; j < tot; j++)
     42         {
     43             if(i * prime[j] > maxn) break;
     44             check[i * prime[j]] = true;
     45             if( i % prime[j] == 0){
     46                 mu[i * prime[j]] = 0;
     47                 break;
     48             }else{
     49                 mu[i * prime[j]] = -mu[i];
     50             }
     51         }
     52     }
     53 }
     54 
     55 ll qpow(ll a, ll b)
     56 {
     57     ll ans=1;
     58     while(b)
     59     {
     60         if(b&1)  ans=(ans*a)%mod;
     61         a=(a*a)%mod;
     62         b>>=1;
     63     }
     64     return ans;
     65 }
     66 
     67 int main()
     68 {
     69     //freopen("in.txt","r",stdin);
     70     Moblus();
     71     int kase=0;
     72     int T;
     73     scanf("%d",&T);
     74     while(T--)
     75     {
     76         memset(cnt,0,sizeof(cnt));
     77         scanf("%d",&n);
     78         int MIN=INF;
     79         int MAX=0;
     80         for(int i=1;i<=n;i++)
     81         {
     82             scanf("%d",&a[i]);
     83             MIN=min(MIN,a[i]);
     84             MAX=max(MAX,a[i]);
     85             cnt[a[i]]++;
     86         }
     87 
     88         num[0]=0;
     89         for(int i=1;i<=200000;i++)   num[i]=num[i-1]+cnt[i];
     90 
     91         ll ans=0;
     92 
     93         for(int i=2;i<=MIN;i++)
     94         {
     95             ll tmp=1;
     96             for(int j=1;j*i<=MAX;j++)
     97             {
     98                 tmp=(tmp*qpow((ll)j,num[i*j+i-1]-num[i*j-1]))%mod;  //快速幂计算,j是GCD的倍数,也就是a【i】/GCD
     99             } 
    100             ans=(ans-tmp*mu[i]+mod)%mod;  
    101         }
    102 
    103         printf("Case #%d: %I64d
    ",++kase,ans);
    104     }
    105     return 0;
    106 }
  • 相关阅读:
    心得体悟帖---200125(不要被掌控)
    心得体悟帖---200125(向下兼容)
    心得体悟帖---200125(那些道理明白是真的明白么)
    日常英语---200121(torment)
    日常英语---200121(英雄联盟英雄双语台词-金属大师莫德凯撒)
    日常英语---200121(respawn)
    日常英语---200121(英雄联盟LOL的英文)
    心得体悟帖---200121(完全的杞人忧天)
    心得体悟帖---200120(录课一举四五得)(痛苦或者不开心的来源)
    日常英语---200120(tiny)
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7248239.html
Copyright © 2020-2023  润新知