hdu1796 How many integers can you find(整除个数统计)

来源:互联网 发布:央视2012年网络春晚 编辑:程序博客网 时间:2024/05/21 10:52

关键词:整除个数统计
题意:统计[1,n)中能够被a[1…m]中至少一个整除的数的总数
m<=10
解法:Aai代表[1,n)中能够被a[i]整除的数的个数
结论:[1,n)中能够被x整除的个数:(n-1)/x
因此
1.|Aai|=(n1)/ai
2.|Aai1Aai2...Aaik|=(n-1)/lcm(ai1,ai2...aik)
由容斥原理:ans=|Aa1Aa2...Aam|
复杂度:O(2mm)

拓展:
1.统计b[1,2…n]中所有数的因子在数组中出现的个数(每个数中仅记做一次)
解法:遍历b[i]的所有因子,遇到因子d时,beinum[d]++即可
复杂度:O(b[i])

2.统计b[1,2…n]中能够被a[1…m]中至少一个整除的数的总数
b数组的取值范围是1-N
解法:输入b[i]时,将b[i]的所有因子k的beinum[k]++,统计出1-max(b[i])中每个数的beinum:b数组中是其倍数的个数。在统计整除个数时,在代码标星的两行将(n-1)/tlcm改为beinum[tlcm]即可
复杂度:O(nN+2mm)

#include<stdio.h>#include<iostream>#include<algorithm>#include<string.h>#include<vector>#define lowbit(x) x&(-x)#define mem(a,b) memset(a,b,sizeof(a))#define ll long longusing namespace std;#define rad 10000const int maxn =100;int gcd(int a,int b){    return (b==0)?a:gcd(b,a%b);}int lcm(int a,int b){    return a*b/gcd(a,b);}int n,m,ans;int a[maxn];bool cmp(int a,int b){    return a>b;}int main(){    //freopen("a.txt","r",stdin);    while(scanf("%d%d",&n,&m)!=EOF){        for(int i=0;i<m;i++) scanf("%d",&a[i]);        sort(a,a+m,cmp);        if(!a[m-1]) m--;        ans=0;        for(int i=1;i<(1<<m);i++){            int tlcm=1,tmp=0;//最小公倍数            for(int j=0;(1<<j)<=i;j++){                if((1<<j)&i){                    tlcm=lcm(tlcm,a[j]);                    if(tmp) tmp=0;                    else tmp=1;                }            }            if(tmp) ans=ans+(n-1)/tlcm;//***            else ans=ans-(n-1)/tlcm;//***        }        printf("%d\n",ans);    }}
0 0