概述
题目:
T
T
T组数据。
每组数据给定一个数
b
b
b,找出一组数
t
t
t,满足
∑
i
=
1
∣
t
∣
t
i
≤
b
displaystyle sum_{i=1}^{|t|}t_i le b
i=1∑∣t∣ti≤b且
v
k
=
(
k
%
t
1
,
k
%
t
2
,
⋯
k
%
t
∣
t
∣
)
v_k=(k%t_1,k%t_2,cdots k%t_{|t|})
vk=(k%t1,k%t2,⋯k%t∣t∣)的种类数最多,其中
k
k
k为非负整数。
(
1
≤
T
,
b
≤
30000
)
(1 le T,b le 30000)
(1≤T,b≤30000)
题解:
考虑什么情况下对于不同的
k
k
k,
v
k
v_k
vk相同。设
k
1
,
k
2
,
k
1
≠
k
2
k_1,k_2,k_1 ne k_2
k1,k2,k1=k2,
k
1
=
a
1
t
1
+
b
1
,
k
1
=
a
2
t
2
+
b
2
,
⋯
k
1
=
a
∣
t
∣
t
∣
t
∣
+
b
∣
t
∣
k_1=a_1t_1+b_1,k_1=a_2t_2+b_2,cdots k_1=a_{|t|}t_{|t|}+b_{|t|}
k1=a1t1+b1,k1=a2t2+b2,⋯k1=a∣t∣t∣t∣+b∣t∣,
k
2
=
c
1
t
1
+
b
1
,
k
2
=
c
2
t
2
+
b
2
,
⋯
k
2
=
c
∣
t
∣
t
∣
t
∣
+
b
∣
t
∣
k_2=c_1t_1+b_1,k_2=c_2t_2+b_2,cdots k_2=c_{|t|}t_{|t|}+b_{|t|}
k2=c1t1+b1,k2=c2t2+b2,⋯k2=c∣t∣t∣t∣+b∣t∣。
那么显然
l
c
m
(
t
1
,
t
2
,
⋯
,
t
∣
t
∣
)
∣
∣
k
2
−
k
1
∣
lcm(t_1,t_2,cdots,t_{|t|})mid|k2-k1|
lcm(t1,t2,⋯,t∣t∣)∣∣k2−k1∣,所以不同的
v
k
v_k
vk有
l
c
m
(
t
1
,
t
2
,
⋯
,
t
∣
t
∣
)
lcm(t_1,t_2,cdots,t_{|t|})
lcm(t1,t2,⋯,t∣t∣)个。显然我们取的
t
t
t要两两互质,不然我们可以在达到原来的
l
c
m
lcm
lcm的同时使总和更小。那么考虑一个数
n
=
p
1
a
1
p
2
a
2
⋯
p
k
a
k
n=p_1^{a_1}p_2^{a_2}cdots p_k^{a_k}
n=p1a1p2a2⋯pkak,有
p
1
a
1
p
2
a
2
⋯
p
k
a
k
≥
p
1
a
1
+
p
2
a
2
+
⋯
+
p
k
a
k
p_1^{a_1}p_2^{a_2}cdots p_k^{a_k}ge p_1^{a_1}+p_2^{a_2}+cdots +p_k^{a_k}
p1a1p2a2⋯pkak≥p1a1+p2a2+⋯+pkak,当且仅当
n
=
4
=
2
×
2
n=4=2 times 2
n=4=2×2时,等号成立,所以我们要找的
t
t
t一定是质数的幂次。打出质数的幂次可以发现就3000个左右,所以问题就变成了分组背包问题了,物品
a
a
a的体积为
a
a
a,价值为
ln
a
ln a
lna,直接
d
p
dp
dp即可。
注意由于
T
T
T很大,所以不要每次都求背包,要直接求30000的背包预处理出所有的答案。感觉有些卡常。
复杂度: O ( b 2 l o g b ) O(frac{b^2}{logb}) O(logbb2)
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<bitset>
#include<sstream>
#include<ctime>
//#include<chrono>
//#include<random>
//#include<unordered_map>
using namespace std;
#define ll long long
#define ls o<<1
#define rs o<<1|1
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
const double pi=acos(-1.0);
const double eps=1e-6;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int maxn=30005;
ll read(){
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int T,b,tp;
int prim[maxn],vis[maxn];
double dp[maxn],ans[maxn],v[5005][20];
int a[5005][20];
void init(int n){
tp=0;
for(int i=2;i<=n;i++){
if(!vis[i]){
prim[++tp]=i;
}
for(int j=1;i*prim[j]<=n;j++){
vis[i*prim[j]]=1;
if(i%prim[j]==0)break;
}
}
for(int i=1;i<=tp;i++){
for(int j=prim[i],k=1;j<=n;j*=prim[i],k++){
a[i][k]=j;
a[i][0]=k;
v[i][k]=log(j);
}
}
for(int i=0;i<=n;i++)dp[i]=-1e18;
dp[0]=0;
for(int i=1;i<=tp;i++){
for(int j=n;j>=prim[i];j--){
for(int k=1;k<=a[i][0];k++){
if(a[i][k]>j)continue;
if(dp[j-a[i][k]]>=0)dp[j]=max(dp[j],dp[j-a[i][k]]+v[i][k]);
}
}
}
ans[0]=dp[0];
for(int i=1;i<=n;i++)ans[i]=max(ans[i-1],dp[i]);
}
int main(void){
// freopen("in.txt","r",stdin);
init(30000);
scanf("%d",&T);
while(T--){
scanf("%d",&b);
printf("%.9fn",ans[b]);
}
return 0;
}
最后
以上就是火星上水壶为你收集整理的gym102798 2020CCPC威海L Clock Master的全部内容,希望文章能够帮你解决gym102798 2020CCPC威海L Clock Master所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复