L - Clock Master ###K //K

题目链接:https://vjudge.net/contest/408015#problem/L
题意:选多个和不超过b的数 使得其公倍数最大
思路:分组背包问题   分组背包的 v要放在 遍历某一组的物品 之外 才能保证同一组的物品只取一次

 模拟一下就可以发现 只需要对质数的正整数幂 分组  即可 注意的是取对数也有复杂度logn

应该用一个数组预处理下  其实质数筛到1000就能过了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define pb push_back
 5 const int mod=1e9+7;
 6 const int maxn=3e4+10;
 7 double dp[maxn];
 8 int vis[maxn];
 9 vector<int>cnt;
10 vector<int>E[maxn];
11 double ln[maxn];
12 
13 
14 int main()
15 {
16     ios::sync_with_stdio(0);
17     cin.tie(0);
18     for(int i=2;i<maxn;i++)
19     {
20         if(vis[i])
21             continue;
22         cnt.pb(i);
23         for(int j=i;j<maxn;j+=i)
24         {
25             vis[j]=1;
26         }
27     }
28     for(int i=2;i<maxn;i++)
29         ln[i]=log(i);
30     int tot=0;
31     for(auto &v:cnt)
32     {
33         ll temp=v;
34         tot++;
35         for(int j=1;j<=20;j++)
36         {
37             E[tot].pb(temp);
38             temp*=v;
39             if(temp>1e5)
40                 break;
41         }
42     }
43     //cout<<cnt.size()<<'\n';
44     for(int i=1;i<=tot;i++)
45     {
46         for(int j=maxn-1;j>=1;j--)
47         {
48             for(auto &v:E[i])
49             {
50                 if(j>=v)
51                     dp[j]=max(dp[j],dp[j-v]+ln[v]);
52             }
53         }
54     }
55     int t;
56     cin>>t;
57     while(t--)
58     {
59         int b;
60         cin>>b;
61         cout<<fixed<<setprecision(9)<<dp[b]<<'\n';
62     }
63 
64 
65 
66 }
View Code

 

posted @ 2020-11-23 23:04  canwinfor  阅读(151)  评论(0)    收藏  举报