C. Maximum Set
题意
给定一个区间[l,r],在这个区间里选择数字组成一个集合,让这个集合的数字都能整除
输出这个集合的数字个数的最大值和能有多少这样大的集合
思路
显然为其中一个所要的集合
也可能是要的集合,当然3的位置可以变换
到这就很明白了,遍历每个数
:::info
:::
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6+10,M=998244353;
int main()
{
int t;
cin>>t;
while(t--)
{
int l,r,tem=1,tem2,si=1;
long long sum=0;
cin>>l>>r;
while(l*tem*2<=r)tem*=2,si++;
tem2=tem/2*3;
//cout<<tem;
for(int i=l;i<=r;i++)
{
if(i*tem>r)break;
if(i*tem<=r)sum=(sum+1)%M;
if(i*tem2<=r)sum=(sum+si-1)%M;
}
cout<<si<<" "<<sum<<'\n';
}
return 0;
}
优化
直接用r去除以就得到了最多能得到几,对于3也是一样的
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6+10,M=998244353;
int main()
{
int t;
cin>>t;
while(t--)
{
int l,r,tem=1,tem2,si=1;
long long sum=0;
cin>>l>>r;
while(l*tem*2<=r)tem*=2,si++;
if(tem==1){cout<<"1 "<<r-l+1<<endl;continue;}
//cout<<r/tem-l;
tem2=tem/2*3;
sum=(r/tem-l+1)%M;
if(l*tem2<=r)sum+=(r/tem2-l+1)*(si-1)%M;
cout<<si<<" "<<sum<<'\n';
}
return 0;
}
D. Maximum Subarray
题意
给你一个由 n 个整数组成的数组 a1,a2,…,an 。也给了两个整数 k 和 x 。您必须执行操作:将 x 添加到恰好 k 个不同位置的元素上,并从所有其他位置减去 x。例如,如果 a=[2,−1,2,3],k=1,x=2, 并且我们选择了第一个元素,那么在操作之后,数组 a=[4,−3,0,1] 。求操作后数组的最大连续子段和。另外空数组字段和为0;
思路
看这个数据范围只能dp了吧,要注意到k最大不超过20
可以先将所有的 ai 都先减去x这样就简化为在k个不同的位置的元素上加上2*x
状态表示 f[i][j] 在前i个数中在 j个位置加上2*x 并以a[i]结尾的连续子段的和
无效状态
:::info
前i个数不够
因为一定要改变k个数,所以后面的数不够改变 :::
状态转移
无效状态没有表示出来 :::info
-
if j==0 f[i][0]=max(f[i-1][0],0)+a[i]
-
** if j!=0 f[i][j]=max(f[i-1][j-1]+a[i],a[i])+2*x
if(i!=j)f[i][j]=max(f[i][j],max(f[i-1][j]+a[i],a[i]));**<br />**
:::
j==0很容易解释
如果j!=0 就要枚举在i位置要不要加 2*x,当然如果i==j就一定要加
答案的获得
这里的每一个有效的f[i][j]都有可能都是答案
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2e5+10;
const long long inf = -1e18;
long long a[N];
long long f[N][21];
int main()
{
int t;
cin>>t;
while(t--)
{
int n,k,x;
f[0][0]=0;
long long sum=0;
cin>>n>>k>>x;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]-=x;
}
for(int i=1;i<=k;i++)f[0][i]=inf;
for(int i=1;i<=n;i++)
{
if(i+k<=n)f[i][0]=max(f[i-1][0],0ll)+a[i];
else f[i][0]=inf;
for(int j=1;j<=k;j++)
{
if(i>=j&&n-i>=k-j)
{
f[i][j]=max(f[i-1][j-1]+a[i],a[i])+2*x;
if(i!=j)f[i][j]=max(f[i][j],max(f[i-1][j]+a[i],a[i]));
}
else f[i][j]=inf;
}
}
for(int i=1;i<=n;i++)for(int j=0;j<=k;j++)sum=max(sum,f[i][j]);
cout<<sum<<endl;
}
}