【2018/11/01搜索大赛T1】cost 数

【题目】

传送门


【分析】

20 pts:

直接枚举。时间复杂度:O ( n m ) (nm) (nm)

另外 40 pts:

过这 40    p t s 40\;pts 40pts,我们需要知道一点小知识:

  • 1 1 1 n n n 的正整数中,能被 x x x 整除的数的个数 n u m x = n x num_x=\frac{n}{x} numx=xn(这里是整除,下同);
  • 1 1 1 n n n 的正整数中,同时被 x x x y y y 整除的数个数 n u m x    a n d    y = n l c m ( x , y ) num_{x\; and\; y}=\frac{n}{ lcm(x,y)} numxandy=lcm(x,y)n l c m lcm lcm 为最小公倍数)。
  • 依此类推,同时被 x 1 , x 2 , . . . , x i x_1,x_2,...,x_i x1,x2,...,xi 整除的数的个数为 n l c m ( x 1 , x 2 , . . . , x i ) \frac{n}{lcm(x_1,x_2,...,x_i)} lcm(x1,x2,...,xi)n

现在回到这道题来

将题目中的式子转化一下: x ≡ 17 ( m o d    a i )    → x    m o d    a i = 17    m o d    a i    → ( x − 17 )    m o d    a i = 0 x≡17 (mod \;a_i)\;\rightarrow x\; mod \;a_i=17 \;mod \;a_i\;\rightarrow(x−17) \;mod \;a_i=0 x17(modai)xmodai=17modai(x17)modai=0(注意已保证 a i > 17 a_i>17 ai>17,所以 17    m o d    a i = 17 17 \;mod \;a_i=17 17modai=17),于是问题变为求 0 0 0 m − 17 m−17 m17 整数中至少能被 a a a 中一个数整除的有多少个。

根据容斥原理, ∣ A ∪ B ∣ = ∣ A ∣ + ∣ B ∣ − ∣ A ∩ B ∣ |A∪B|=|A|+|B|−|A∩B| AB=A+BAB ∣ A ∣ |A| A 表示集合 A A A 元素个数),可得 1 1 1 n n n 的正整数中,能被 x x x y y y 整除的数个数 n u m x    o r    y = n u m x + n u m y − n u m x    a n d    y = n x + n y − n l c m ( x , y ) num_{x\; or\; y}=num_x+num_y-num_{x \;and\; y}=\frac{n}{x}+\frac{n}y-\frac n{lcm(x,y)} numxory=numx+numynumxandy=xn+ynlcm(x,y)n。对于三个数 x x x y y y z z z 的情况,只要类比一下,画画图就可以知道:

n u m x    o r    y    o r    z = n u m x + n u m y + n u m z − n u m x    a n d    y − n u m x    a n d    z − n u m y    a n d    z + n u m x    a n d    y    a n d    z = n x + n y + n z − n l c m ( x , y ) − n l c m ( x , z ) − n l c m ( y , z ) + n l c m ( x , y , z ) num_{x\; or\; y\; or\; z}=num_x+num_y+num_z-num_{x \;and\; y}-num_{x\; and\; z}-num_{y \;and\; z}+num_{x \;and \;y \;and\; z}=\frac{n}{x}+\frac{n}{y}+\frac{n}{z}-\frac{n}{lcm(x,y)}-\frac{n}{lcm(x,z)}-\frac{n}{lcm(y,z)}+\frac{n}{lcm(x,y,z)} numxoryorz=numx+numy+numznumxandynumxandznumyandz+numxandyandz=xn+yn+znlcm(x,y)nlcm(x,z)nlcm(y,z)n+lcm(x,y,z)n

时间复杂度:O ( l o g    m ) (log\;m) (logm)

100 pts:

容斥原理是可以扩展到 n n n 个集合的,具体就是口诀:奇加偶减

这时我们需要用个 d f s dfs dfs 枚举每个 a i a_i ai 选与不选,若选出 k k k 个数,且 k k k 为奇数,则 a n s ans ans 加上 m l c m \frac{m}{lcm} lcmm(这里的 l c m lcm lcm 就是选出的数的最小公倍数,下同),若为偶数 a n s ans ans 减去 m l c m \frac{m}{lcm} lcmm

当然,这个算法复杂度还比较大,还要加上优化,包括可行性剪枝(选出的数的 l c m lcm lcm 要小于等于 m m m。由于 a i > 17 a_i>17 ai>17,该剪枝十分有效)、优化搜索顺序(先搜大数)。

时间复杂度:O ( 2 n ∗ l o g    m ) (2^n*log\;m) (2nlogm)(实际小得多)


【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 105
#define ll long long
using namespace std;
int n,m,ans,a[N];
bool comp(int a,int b)  {return a>b;}
ll Lcm(ll a,ll b)  {return a*b/__gcd(a,b);}
void dfs(int x,int num,ll lcm)
{
	if(lcm>m)  return;
	if(x>n&&lcm==1)  {ans++;return;}
	if(x>n)  {num&1?ans+=m/lcm:ans-=m/lcm;return;}
	dfs(x+1,num,lcm),dfs(x+1,num+1,Lcm(lcm,a[x]));
}
int main()
{
//	freopen("count.in","r",stdin);
//	freopen("count.out","w",stdout);
	int i;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;++i)
	  scanf("%d",&a[i]);
	sort(a+1,a+n+1,comp);
	m-=17,dfs(1,0,1);
	printf("%d",ans);
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值