SPOJ MSKYCODE - Sky Code

莫比乌斯&筛法

题目链接 Sky Code

题意:

给出一个大小为n的集合,求出满足条件的4元子集的个数。
这个条件就是:该四元子集{a,b,c,d} ,满足 gcd(a,b,c,d)=1

思路

第一步算法分析:
☞第一感觉就是容斥原理,原命题等价:
☞记Ai为gcd(a,b,c,d)=i的集合个数
☞ans=C(n,4)-A2-A3-A5...+(A2x3+A2x5+...)-(A2x3x5...)
☞再一看数据量:1e4 bingo,很小,果断mobius打表直接做了。
☞最后mobius下的公式就是:
☞ans=∑mobius[i]*Ai
第二步复杂度分析:
☞1e4 下mobius打表忽略不计
☞求Ai 这个是比较常见的思路分两步走
☞1.求出是2,3,4,6,7...的倍数的集合元素个数Si
☞那么Ai=C ( Si , 4 ).
☞这个求法有两种思路
☞暴力求解

for(int i=0;i<n;i++){
    for(int j=0;j<=data[i];i++){
        if(data[i]%j==0) num[j]++;
    }
}

☞复杂度 O(n * max(data[i])) 对于这里也就1e4 * 1e4估计还是可以的,但正式比赛肯定不行。
☞筛法

        
        for(int i=2;i<=Max;i++){
            for(int j=i;j<=Max;j+=i){
                if(vis[j]) num[i]++;
            }
        }
        

☞复杂度 Maxlg(Max) 这个一般就可以了,还有一种 sqrt(Max)lg(Max)的,我也不是很会写 ,有兴趣的可以加我qq讨论下 844704...
☞2.最后求下c(a,i) 就可以了
☞这个也要预处理 c(n,m)=c(n-1,m-1)+c(n-1,m)
剪枝思考&&debug
☞这个步骤很重要,也是区别1次AC和5次AC的分水岭
☞给出几个简单的剪枝
☞n<4 直接为0
☞Max压缩筛法数据范围
☞debug 核心在于构造边界数据,这点我也是菜鸟
☞分享几个自己当是用到的:
☞c(10000,4)<51e14 longlong ok
☞1e4
*ln(1e4)< 1e9(一般算法大于这个基本是出不来的....)

下面给出AC代码:

//
//  main.cpp
//  MSKYCODE - Sky Code
//
//  Created by ccccsober on 6/25/16.
//  Copyright © 2016 cccsober. All rights reserved.
//

#include <iostream>
#include <algorithm>
#include <cassert>
#include <string>
#include <sstream>
#include <math.h>
#include <set>
#include <bitset>
#include <vector>
#include <stack>
#include <map>
#include <queue>
#include <deque>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cctype>
#include <complex>
using namespace std;
const int MAX1= 20000  ;
//const int Mod=   ;
const double plus=0.49999999;
const int INF=0x3f3f3f3f;
typedef long long LL;
typedef unsigned long long ULL;
#define M_PI 3.141592653589
int num[MAX1];
LL multi[MAX1][5];
int mobius[MAX1];
int data[MAX1];
bool vis[MAX1];
vector<int> prime;
void Multi(){
    for(int i=0;i<MAX1;i++)
        multi[i][0]=1;
    for(int i=1;i<MAX1;i++){
        for(int j=1;j<5;j++){
            multi[i][j]=multi[i-1][j-1]+multi[i-1][j];
        }
    }
}
void Mobius(){
    memset(vis,0,sizeof(vis));
    mobius[1]=1;
    for(int i=2;i<MAX1;i++){
        if(!vis[i]){
            prime.push_back(i);
            mobius[i]=-1;
        }
        for(int j=0;j<prime.size() && i*prime[j]<MAX1;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j])
                mobius[i*prime[j]]=-mobius[i];
            else{
                mobius[i*prime[j]]=0;
                break;
            }
        }
    }
    
}
void _init(){
    memset(num,0,sizeof(num));
    memset(vis,0,sizeof(vis));
}
int main(int argc, const char * argv[]) {
    freopen("/Users/sperc4/Desktop/input.txt", "r", stdin);
    int n;
    Mobius();
    Multi();
    while(scanf("%d",&n)!=EOF){
        _init();
        int Max=-INF;
        int t;
        for(int i=0;i<n;i++){
            scanf("%d",&t);
            Max=max(Max,t);
            vis[t]=1;
//            for(int j=0;prime[j]<=t;j++){           //这个位置RT了一发
//                if(t%prime[j]) continue;
//                num[prime[j]]++;
//            }
        }
        if(n<4) {cout<<"0"<<endl;continue;}
        
        for(int i=2;i<=Max;i++){
            for(int j=i;j<=Max;j+=i){
                if(vis[j]) num[i]++;
            }
        }
        
        
        
        LL ans=0;
        for(int i=1;i<=Max;i++){
            ans+=(LL)mobius[i]*multi[num[i]][4];
        }
        printf("%lld\n",multi[n][4]+ans);
    }
    return 0;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容