您的位置:首页 > 其它

HPUOJ WitchMirror 【容斥】or 【状态压缩+容斥】

2017-07-20 18:24 183 查看
王炸的队友地雷(你可以叫他雷雷)要考科一了,但地雷总是不太自信,因为他看的题太少了。

王炸为了帮他,就拿出来了一面魔镜,这个魔镜可以告诉雷雷他还不会的题有多少。但是魔镜自诩是hpu毕业的高材生,并不想直接了当的告诉地雷,他通过以下这种方式让地雷自己计算出来:

魔镜给地雷m个数字(a1、a2 …… am)和一个整数n,魔镜定义:如果有一个数,是这m个数字里面任意一个数的倍数,那么这个数称为LuckyNumber。而雷雷会的题数为[1,n]闭区间内LuckyNumber的数量。

那么请你帮地雷计算一下他会的题目数。

输入

有多组数据,每组数据第一行给出两个字母n、m,含义如题意所示。

数据第二行给出m个整数:a1、a2 …… am。

(1≤ n、a1、a2 …… am ≤ 1e9,1 ≤ m ≤ 15 )

输出

输出一个整数,表示地雷会的题目数。

样例输入

10 2

5 7

100 1

1

样例输出

3

100

代码

// 56ms ac

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int MAXN = 1e5;
const int MAXM = 3000000;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8 ;
/*------------------------------*/
LL gcd(LL a,LL b){
return b==0?a:gcd(b,a%b);
}
LL lcm(LL a,LL b){
return a/gcd(a,b)*b;
}
LL p[20];
LL ge;
LL nop(LL m){
LL que[MAXN];
LL top=0;
que[top++]=-1;
for(int i=0;i<ge;i++){
LL temp=top;
for(int j=0;j<temp;j++){ // 这里也是控制了 奇加偶减。
LL f=1;
if(que[j]<0) f=-1;
que[top++]=f*lcm(abs(que[j]),p[i])*(-1);
}
}

LL sum=0;
for(LL i=1;i<top;i++){
sum+=m/que[i];
}
return sum;
}
int main(){
LL m;  LL n;
while(~scanf("%lld%lld",&n,&m)){
for(int i=0;i<m;i++) scanf("%lld",&p[i]);
ge=m;
printf("%lld\n",nop(n));
}
return 0;
}


2017 11 3

今天又做到一个容斥,用了状态压缩的姿势来枚举所有的情况,感觉很棒。 学习一下。

/ / 重复算了好多 gcd 和lcm 导致慢了好多 200+ms

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>pii;
#define first fi
#define second se
#define  LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)

const int MAXN = 30;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
LL gcd(LL a,LL b){
return b==0?a:gcd(b,a%b);
}
LL lcm(LL a,LL b){
return a/gcd(a,b)*b;
}

LL a[MAXN];
int main(){
CLOSE();
//  fread();
//  fwrite();
LL n,m;
while(scanf("%lld%lld",&n,&m)!=EOF){
for(int i=0;i<m;i++) scanf("%lld",&a[i]);
LL ans=0;
for(int i=1;i<(1<<m);i++){  //
int cnt=0;  LL LCM = 1;
for(int j=0;j<m;j++){
if(1&(i>>j)) {
cnt++;
LCM=lcm(LCM,a[j]);
}
}
if(cnt&1) ans+=n/LCM;// 奇加偶减
else ans-=n/LCM;
}
printf("%lld\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: