cost數
描述
“給你一個有n個正整數的數列{an}。一個正整數x若滿足在數列{an}中存在一個正整數ai,使x≡17(mod ai),那麼x就是一個‘cost數’。請問1到m的正整數中,有多少個‘cost數’?”
輸入
第一行兩個正整數n和m,意義見問題描述。
第二行n個正整數,分別爲數列{an}中的n個數。
輸出
輸出一個整數,表示1到m中“cost數”的個數。
樣例輸入
3 100
18 22 23
樣例輸出
11
【數據範圍】
對於20%的數據,有n≤20,m≤100,000;
另有40%的數據,n≤3,m<2^31;
對於100%的數據,有n≤30,m<231,17<ai<231。
(注:“≡”爲同餘符號,a≡b (mod k) 即a mod k = b mod k)
Analysis
考場上推了半天,倒是想出了容斥……奇加偶減。很好做啊,然後很多很多的怎麼弄啊
後來看題解發現就是dfs看每個數選還是不選,如果這次選出來的數個數爲奇,就,否則就減
最後再把(17沒有被算)就可以得到答案了
再順手剪剪枝,比如:
當前時就不用繼續了
還有些細節要注意一下:
比如這樣寫是錯誤的
具體原因就是因爲我們剪了枝,會導致多算的17沒有被減或者減多了
Code
#include<bits/stdc++.h>
#define in read()
#define ll long long
using namespace std;
inline int read(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){
res=(res<<3)+(res<<1)+ch-'0';
ch=getchar();
}
return f==1?res:-res;
}
int n,m,a[40];
ll ans=0;
ll gcd(ll x,ll y){
ll z=x%y;
while(z){x=y;y=z;z=x%y;}
return y;
}
ll LCM(ll x,ll y){return x/gcd(x,y)*y;}
void dfs(int pos,ll lcm,int cnt){
if(pos==0){
if(lcm==1) return;//什麼都不選的時候就沒有意義啦
if(cnt&1) ans+=(m-17)/lcm;
else ans-=(m-17)/lcm;
return;
}
if(lcm>m) return;
ll tmp=LCM(lcm,a[pos]);
if(tmp<=m) dfs(pos-1,tmp,cnt+1);
dfs(pos-1,lcm,cnt);
}
int main(){
n=in;m=in;
int i,j,k;
for(i=1;i<=n;++i) a[i]=in;
sort(a+1,a+n+1);
dfs(n,1,0);
cout<<ans+1;
return 0;
}