JZOJ 1241. Number
题目
分析
- 考场只会打暴力(50)
- 然后原来是个二分
- 枚举mid前有k个满足的数
- 我们可以求出输入的数的lcm
- 然后容斥就好啊
代码
1 #include<iostream> 2 #include<algorithm> 3 #define ll long long 4 using namespace std; 5 int a[20]; 6 int b[20]; 7 int n,k; 8 struct sb 9 { 10 ll v,num; 11 }l[100001]; 12 int cnt=0; 13 bool cmp(sb a,sb b) 14 { 15 if (a.num<b.num) return true; 16 return false; 17 } 18 ll gcd(ll a,ll b){ 19 if(a%b==0) return b; 20 else return gcd(b,a%b); 21 } 22 ll lcm(ll a,ll b){ 23 return a*b/gcd(a,b); 24 } 25 void dfs(int f,int gs) 26 { 27 if (gs>n) return; 28 long long p=1; 29 for (int i=1;i<=gs;i++) 30 { 31 p=lcm(p,b[i]); 32 if (p>1000000000000000) return; 33 } 34 l[++cnt].num=gs; l[cnt].v=p; 35 for (int i=f+1;i<=n;i++) 36 { 37 b[gs+1]=a[i]; 38 dfs(i,gs+1); 39 } 40 } 41 int main () 42 { 43 cin>>n>>k; 44 for (int i=1;i<=n;i++) 45 cin>>a[i]; 46 for (int i=1;i<=n;i++) 47 { 48 b[1]=a[i]; 49 dfs(i,1); 50 } 51 sort(l+1,l+1+cnt,cmp); 52 ll lll=1,r=1e15,mid; 53 while (lll<=r) 54 { 55 mid=lll+r>>1; 56 ll kk=0; 57 for (int i=1;i<=cnt;i++) 58 if (l[i].num%2==1) kk+=mid/l[i].v*l[i].num; 59 else kk-=mid/l[i].v*l[i].num; 60 if (kk<k) lll=mid+1; 61 else r=mid-1; 62 } 63 cout<<lll; 64 }
为何要逼自己长大,去闯不该闯的荒唐