POJ3094 Sky Code(莫比乌斯反演)

POJ3094 Sky Code(莫比乌斯反演)

Sky Code

题意

给你\(n\le 10^5\)个数,这些数\(\le 10^5\),问这些这些数组成的互不相同的无序四元组(a,b,c,d)使得gcd(a,b,c,d)=1的四元组有多少?

解法

枚举一个约数\(k\),看看总共有多少个数\(S_k=\{x\}\)满足\(k|x\)。那么可以保证(a,b,c,d)有的一个共同的因子是k,这样的四元组的个数就是
\[
F(k)={|S_k|\choose 4}
\]
这样算会算重,比如枚举到\(k=4\)再枚举到\(k=2\),这两者的方案显然有重复,加入有一个四元组满足有一个共同约数是4,那么他们一定也可以满足有一个共同约数是2。我们记\(f(x)=\)最大公因数是\(x\)的四元组的数量。上面的那个大\(F(x)\)就表示有一个公因数(不是最大公因数)是\(x\)的四元组的数量

我们数学模型化这个算重的关系:
\[
F(n)=\Sigma_{d|x}f(d)
\]
这不就是莫比乌斯反演可以解决的嘛 piece of cake
\[
f(x)=\Sigma_{x|d}\mu(d)F(d)
\]
那么(看不懂请右上角)
\[
\Sigma f(x)=\Sigma_i\mu(i)F(i)
\]
Q:你这样不是O(n^2)吗,你怎么实现可以在正确的复杂度内得到每个数所有的因数?

A:开个桶表示每个\(|S_k|\),枚举\(i\in 2-\sqrt x\),把\(i\)和\(x/i\)都丢在桶里计数。复杂度\(O(n^{1.5})\)注意当\(i=x/i\)的时候只算一次!

//@winlere
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;  typedef long long ll;
template < class ccf > inline ccf qr(ccf ret){      ret=0;
      register char c=getchar();
      while(not isdigit(c)) c=getchar();
      while(isdigit(c)) ret=ret*10+c-48,c=getchar();
      return ret;
}

const int maxn=1e4+1;
ll c[maxn][5];
int n;
ll ans;
int buk[maxn];
int cnt[maxn];
bool data[maxn];
int mu[maxn];
bool usd[maxn];
vector < int > ve;

inline void pr(){
      usd[1]=1;mu[1]=0;
      for(register int t=2;t<maxn;++t){
        if(not usd[t]) ve.push_back(t),mu[t]=-1;
        for(register int i=0,edd=ve.size();i<edd;++i){
          register int k=ve[i];
          if(1ll*k*t>maxn)break;
          usd[k*t]=1;
          if(t%k==0) break;
          mu[k*t]=-mu[t];
        }
      }
}

int main(){
      c[0][0]=1;
      pr();
      for(register int t=1;t<maxn;++t){
        c[t][0]=1;
        for(register int i=1;i<=4;++i)
          c[t][i]=c[t-1][i-1]+c[t-1][i];
      }
      while(~scanf("%d",&n)){
        ans=c[n][4];
        memset(buk,0,sizeof buk);
        for(register int t=1,data;t<=n;++t){
          ++buk[data=qr(1)];
          for(register int i=2;i*i<=data;++i)
            if(data%i==0)
                  if(++buk[i],data/i!=i) ++buk[data/i];
        }
        for(register int t=1;t<maxn;++t)
          if(buk[t]>=4&&mu[t])
            ans+=mu[t]*c[buk[t]][4];
        printf("%lld\n",ans);
      }
      return 0;
}

原文地址:https://www.cnblogs.com/winlere/p/10828681.html

时间: 2024-12-17 05:45:02

POJ3094 Sky Code(莫比乌斯反演)的相关文章

POJ Sky Code 莫比乌斯反演

N. Sky Code Time Limit: 1000ms Case Time Limit: 1000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main Submit Status Font Size: + - Stancu likes space travels but he is a poor software developer and will never be able

hdu.5212.Code(莫比乌斯反演 &amp;&amp; 线性筛)

Code Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 300    Accepted Submission(s): 124 Problem Description WLD likes playing with codes.One day he is writing a function.Howerver,his computer b

POJ 3904 Sky Code (容斥+莫比乌斯反演)

Sky Code Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1831   Accepted: 570 Description Stancu likes space travels but he is a poor software developer and will never be able to buy his own spacecraft. That is why he is preparing to ste

Code( BestCoder Round #39 ($) C) (莫比乌斯反演)

Code Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 209    Accepted Submission(s): 85 Problem Description WLD likes playing with codes.One day he is writing a function.Howerver,his computer br

BZOJ 1114 Number theory(莫比乌斯反演+预处理)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=71738 题意:给你一个整数序列a1, a2, a3, ... , an.求gcd(ai, aj) = 1 且 i < j的对数. 思路:利用莫比乌斯反演很快就能得到公式,但是求解时我们要知道序列中1, 2, 3, ... , max(a1, a2, ... , an)的倍数各是多少.我们用num[i]=k,来表示序列中有k个数是i的倍数,那么这部分对结果的影响是m

bzoj 1101 [POI2007]Zap - 莫比乌斯反演

Description FGD正在破解一段密码,他需要回答很多类似的问题:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a ,y<=b,并且gcd(x,y)=d.作为FGD的同学,FGD希望得到你的帮助. Input 第一行包含一个正整数n,表示一共有n组询问.(1<=n<= 50000)接下来n行,每行表示一个询问,每行三个 正整数,分别为a,b,d.(1<=d<=a,b<=50000) Output 对于每组询问,输出到输出文件zap.out一个正

莫比乌斯反演 - HNU 13412 Cookie Counter

Cookie Counter Problem's Link: http://acm.hnu.cn/online/?action=problem&type=show&id=13412&courseid=0 Mean: 将N分为D份,每份不超过X,有多少种分法? analyse: 莫比乌斯反演的运用. 首先我们想到的是迭代,但是数据太大,一路迭代下去必定爆栈+超内存+TLE. 那么就需要用莫比乌斯反演来优化多项式求和.我们枚举X,对于满足条件的X,使用莫比乌斯反演求和统计答案,不满足条

【莫比乌斯反演】BZOJ2005 [NOI2010]能量采集

Description 求sigma gcd(x,y)*2-1,1<=x<=n, 1<=y<=m.n, m<=1e5. Solution f(n)为gcd正好是n的(x,y)的个数 F(n)为gcd是n的倍数的(x,y)的个数 我们要求的就是f(i) 然而这个不好直接算,可F(i)可以直接用(n/i)*(m/i)得到 那么有F(n)=sigma n|i f(i) 于是有f(n)=sigma n|i mu(i)*F(i) 这就是莫比乌斯反演,不过这道题直接用容斥的思想想也很容易

【莫比乌斯反演】BZOJ1101 [POI2007]zap

Description 回答T组询问,有多少组gcd(x,y)=d,x<=a, y<=b.T, a, b<=4e5. Solution 显然对于gcd=d的,应该把a/d b/d,然后转为gcd=1计算 计算用莫比乌斯反演相信大家都会 关键是有T组询问n^2会T 于是有这样一个优化可以做到每次sqrt(n) 每一次是ret+=mu[i]*(n/i)*(m/i) 可是除法向下取整所以会导致很多i的(n/i)*(m/i)一样 具体来说,向下取整得到的结果一定是约数所以对于(n/i)最多2sq