HDU 1796 How many integers can you find

How many integers can you find

Time Limit: 12000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6362    Accepted Submission(s): 1829


Problem Description
  Now you get a number N, and a M-integers set, you should find out how many integers which are small than N, that they can divided exactly by any integers in the set. For example, N=12, and M-integer set is {2,3}, so there is another set {2,3,4,6,8,9,10}, all the integers of the set can be divided exactly by 2 or 3. As a result, you just output the number 7.
 

Input
  There are a lot of cases. For each case, the first line contains two integers N and M. The follow line contains the M integers, and all of them are different from each other. 0<N<2^31,0<M<=10, and the M integer are non-negative and won’t exceed 20.
 

Output
  For each case, output the number.
 

Sample Input
  
  
12 2 2 3
 

Sample Output
  
  
7
 

Author
wangye
 

Source
 

Recommend
wangye   |   We have carefully selected several similar problems for you:   1793  1794  1797  1795  1798 
 
题目大意:

给出一个大整数 n, 给出 m 个大整数 a1,a2,a3...a m;
求出 1 - n-1  中, m 个数的倍数有多少

思路:

容斥原理的应用,这个题和当时有个校赛的题目很相似。题目叫 我是好人  其实是个大骗子、当时还不会容斥,没写出来。
后来老师上课讲了用 dfs 实现容斥原理,感觉很厉害!!
1 - n-1 中  a  的倍数有  n-1 / a 个,1 -n-1 中 b 的倍数有 n-1/b个,但是如果简单相加的话,就会把 a 和 b 的倍数重复相加一遍,所以要用到容斥原理进行避免这一个问题。
简单来说就是   n-1/a  +  n-1 / b    -    n-1/lcm(a,b)

感想:

啦啦~~觉得自己越来越厉害啦~嘻嘻。
给贴出一个容斥原理讲的特别好的 地址
传送门就绪~


AC代码:

#include<iostream>
#include<stdio.h>
using namespace std;
long long int a[15];
long long int sum,n,pp;
long long int gcd(long long int a,long long int b)
{
    if(b==0)
        return a;
    return gcd(b,a%b);
}
void dfs(int pre,long long int lcm,int nowdep)
{
    int i;
    lcm=a[pre]*lcm/gcd(a[pre],lcm);
    if(nowdep&1)
        sum+=(n-1)/lcm;
    else
        sum-=(n-1)/lcm;
    for(i=pre+1;i<pp;i++)
        dfs(i,lcm,nowdep+1);
}
int main()
{
    int i,m,t;
    long long int temp;
    while(~scanf("%I64d%d",&n,&m))
    {
        pp=sum=0;
        for(i=0;i<m;i++)
        {
            scanf("%I64d",&temp);
            if(temp!=0)
            {
                a[pp]=temp;
                pp++;
            }
        }
        for(i=0;i<pp;i++)
            dfs(i,a[i],1);
        cout<<sum<<endl;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值