HDU 1796 How many integers can you find
题意: 求小于n 的数中有多少个不同的数是 m个数中的某一个的倍数。
思路:容斥原理,假如m=2 ,ans=n/a[1]+n/a[2]-n/lcm(a1,a2);
其他同理,那么最坏的情况就是 o(2^m) 的复杂度。
还有一种方法是用DP 来做,但是DP 没学好,代码难理解就直接贴出来了。
需要注意的是这个题有坑,大坑。
代码: 应该是DP 做法吧,我是直接找白书上一个相似的题敲的。 936ms
#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include <bits/stdc++.h>
#include<string>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#define maxn 10010
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MOD 1000000007
#define ll long long
using namespace std;
int n,m;
int A[20];
ll gcd(ll a,ll b)
{
if(!b)
return a;
return gcd(b,a%b);
}
void solve()
{
ll res=0;
for(int i=1;i< (1<<m); i++)
{
int num=0;
for(int j=i; j!=0; j>>=1) num+=j&1;
ll lcm=1;
for(int j=0; j<m; j++)
{
if(i>> j & 1)
{
lcm=lcm/abs(gcd(lcm,A[j]))*A[j];
if(lcm>n) break;
}
}
if(num%2==0) res-=n/lcm;
else res+=n/lcm;
}
printf("%lld\n",res);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
n--;
int x;
for(int i=0;i<m;i++)
{
scanf("%d",&x);
if(x==0) m--,i--;
else A[i]=x;
}
solve();
}
return 0;
}
dfs 312ms
#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include <bits/stdc++.h>
#include<string>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#define maxn 10010
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MOD 1000000007
#define ll long long
using namespace std;
int n,m,cnt;
long long ans,a[30];
long long gcd(long long a,long long b){
return b==0?a:gcd(b,a%b);
}
void DFS(int cur,long long lcm,int id)
{
lcm=a[cur]/gcd(a[cur],lcm)*lcm;
cout<<"ANS "<<ans<<endl;
cout<<"CuR "<<cur<<" LCM "<<lcm<<" ID "<<id<<endl;
if(id&1)
ans+=n/lcm;
else
ans-=n/lcm;
for(int i=cur+1;i<cnt;i++)
DFS(i,lcm,id+1);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
cnt=0;
int x;
while(m--)
{
scanf("%d",&x);
if(x!=0)
a[cnt++]=x;
}
ans=0;
for(int i=0;i<cnt;i++)
DFS(i,a[i],1);
cout<<ans<<endl;
}
return 0;
}