给定一个整数 nn 和 mm 个不同的质数 p1,p2,…,pmp1,p2,…,pm。
请你求出 1∼n1∼n 中能被 p1,p2,…,pmp1,p2,…,pm 中的至少一个数整除的整数有多少个。
输入格式
第一行包含整数 nn 和 mm。
第二行包含 mm 个质数。
输出格式
输出一个整数,表示满足条件的整数的个数。
数据范围
1≤m≤161≤m≤16,
1≤n,pi≤1091≤n,pi≤109
输入样例:
10 2
2 3
输出样例:
7
正确答案:
#include <bits/stdc++.h> #define fi first #define se second using namespace std; const int N=20; const int M=2e5+10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; typedef long long LL; typedef pair<int,int>PII; typedef pair<LL,LL>PLL; LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;} LL lcm(LL a,LL b) {return a/gcd(a,b)*b;} LL lowbit(LL a){return a&-a;} //8个方向的和4个方向的是不同的计算方法 //typedf属于类型替代 //define 属于名字替代 LL n,m; LL a[N]; LL ans; int main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=m;i++) scanf("%lld",&a[i]); for(int i=1;i<(1<<m);i++) { LL cnt=0; LL res=1;//处理乘积 for(int j=0;j<m;j++) { if((i>>j)&1) { if(res>n) { res=-1; break; } cnt++; res*=a[j+1]; } } if(res!=-1) { if(!(cnt%2))ans-=n/res; else ans+=n/res; } } cout<<ans<<endl; return 0; }
错误答案:
#include <bits/stdc++.h> #define fi first #define se second using namespace std; const int N=20; const int M=2e5+10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; typedef long long LL; typedef pair<int,int>PII; typedef pair<LL,LL>PLL; LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;} LL lcm(LL a,LL b) {return a/gcd(a,b)*b;} LL lowbit(LL a){return a&-a;} //8个方向的和4个方向的是不同的计算方法 //typedf属于类型替代 //define 属于名字替代 LL n,m; LL a[N]; LL ans; int main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=m;i++) scanf("%lld",&a[i]); for(int i=1;i<(1<<m);i++) { LL cnt=0; LL res=1;//处理乘积 for(int j=0;j<m;j++) { if((i>>j)&1) { cnt++; res*=a[j+1]; } } if(!(cnt%2))ans-=n/res; else ans+=n/res; } cout<<ans<<endl; return 0; }
注意这两个区别在于进行了res的特判,如果他的数值大于n,就跳过 ,因为这么多数据相乘,一定会造成溢出LL。
然而大于他的数值可以直接省略去的
阶乘不注意之间会造成LL的数据溢出的.