zoukankan      html  css  js  c++  java
  • nyoj CO-PRIME 莫比乌斯反演

    CO-PRIME

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:3
     
    描述

    This problem is so easy! Can you solve it?

    You are given a sequence which contains n integers a1,a2……an, your task is to find how many pair(ai, aj)(i < j) that ai and aj is co-prime.

     
    输入
    There are multiple test cases.
    Each test case conatains two line,the first line contains a single integer n,the second line contains n integers.
    All the integer is not greater than 10^5.
    输出
    For each test case, you should output one line that contains the answer.
    样例输入
    3
    1 2 3
    样例输出
    3

    思路: http://blog.csdn.net/lyhvoyage/article/details/38455415应该是出题的人吧。

      分析:莫比乌斯反演。

      此题中,设F(d)表示n个数中gcd为d的倍数的数有多少对,f(d)表示n个数中gcd恰好为d的数有多少对,

      则F(d)=∑f(n) (n % d == 0)

      f(d)=∑mu[n / d] * F(n) (n %d == 0)

     上面两个式子是莫比乌斯反演中的式子。

      所以要求互素的数有多少对,就是求f(1)。

      而根据上面的式子可以得出f(1)=∑mu[n] * F(n)。

      所以把mu[]求出来,枚举n就行了,其中mu[i]为i的莫比乌斯函数。

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<cstring>
     4 #include<cstdlib>
     5 using namespace std;
     6 const int N = 1e5+1;
     7 
     8 int vis[N];
     9 int mu[N];
    10 int prime[N],cnt;
    11 int date[N];
    12 long long ys[N];
    13 int num[N];
    14 void init()
    15 {
    16     memset(vis,0,sizeof(vis));
    17     mu[1] = 1;
    18     cnt = 0;
    19     for(int i=2;i<N;i++)
    20     {
    21         if(!vis[i])
    22         {
    23             prime[cnt++] = i;
    24             mu[i] = -1;
    25         }
    26         for(int j = 0;j<cnt&&i*prime[j]<N;j++)
    27         {
    28             vis[i*prime[j]] = 1;
    29             if(i%prime[j]) mu[i*prime[j]] = -mu[i];
    30             else
    31             {
    32                 mu [i *prime[j]] = 0;
    33                 break;
    34             }
    35         }
    36     }
    37 }
    38 int main()
    39 {
    40     int n,maxn;
    41     init();
    42     while(scanf("%d",&n)>0)
    43     {
    44         memset(num,0,sizeof(num));
    45         memset(ys,0,sizeof(ys));
    46         maxn = -1;
    47         for(int i=1;i<=n;i++){
    48             scanf("%d",&date[i]);
    49             num[date[i]] ++;
    50             if(date[i]>maxn) maxn = date[i];
    51         }
    52         /***计算F(N)*/
    53         for(int i=1;i<=maxn;i++)
    54         {
    55             for(int j=i;j<=maxn;j=j+i)
    56             {
    57                 ys[i] = ys[i] + num[j];
    58             }
    59         }
    60         long long sum = 0;
    61         for(int i=1;i<=maxn;i++){
    62             long long tmp = (long long)ys[i] *( ys[i]-1 )/2;
    63              sum = sum + mu[i]*tmp;
    64         }
    65 
    66         printf("%I64d
    ",sum);
    67     }
    68     return 0;
    69 }
  • 相关阅读:
    JS弹出一个等待对话框,js iframe等待 推荐一下
    netsuite 支持的字段计算函数 oracle 函数
    js 动态创建iframe 后submit提交
    netsuite凭证批量打印中涉及的html分页打印问题,页面的部分打印
    1099MISC是什么
    debit,credit,日记帐就是每天都要登的帐
    netsuite SyncQtyRate
    netsuite与首信易支付(v4.3)接口
    呼叫中心(Call Center)介绍及产品功能列表
    Js MD5加密问题
  • 原文地址:https://www.cnblogs.com/tom987690183/p/3902399.html
Copyright © 2011-2022 走看看