题目链接:Click here~~
题意:
给你一个集合M,里面最多有10个非负数,问1~n-1中一共有多少个数可以被其中一个整除。
解题思路:
比较简单的容斥吧,可惜我WA了一个下午。
很容易的想到,ans = sum{ 整除一个的数 } - sum{ 整除两个的数 } + sum{ 整除三个的数 } - …… 。
而整除 k 个数的数可以表示成 lcm(A1,A2,…,Ak) 的倍数的形式。
而我的错误出在哪里了呢?
就是思维定势,直接套了上次那个程序,结果发现有一个剪枝条件在这里是不适用的。
假设b<c,则如果lcm(a,b)大于x,lcm(a,c)不一定大于x。
这算是本题的一个收获吧,另外,我把dfs的参数也弄少了,看着清爽了些。
#include <stdio.h> #include <algorithm> using namespace std; typedef __int64 LL; int fac[12],top,ans,n; int gcd(int a,int b) { return b ? gcd(b,a%b) : a; } int lcm(int a,int b) { return a/gcd(a,b)*b; } void dfs(int i,int cnt,int num,int m) { if(cnt == m) { int sum = (n-1)/num; m&1 ? ans += sum : ans -= sum; return ; } if(top-i < m-cnt) return ; int LCM = lcm(num,fac[i]); if(LCM <= n-1) dfs(i+1,cnt+1,LCM,m); dfs(i+1,cnt,num,m); } int sovle() { ans = 0; for(int m=1;m<=top;m++) dfs(0,0,1,m); return ans; } int main() { while(~scanf("%d%d",&n,&top)) { for(int i=0;i<top;i++) { scanf("%d",&fac[i]); if(!fac[i]) i--,top--; } printf("%d\n",sovle()); } return 0; }