A:隔离
qwq题目看错了。
题目描述
鸡尾酒要从 A 地去 B 地办 n 件事,其中第 iii 件事耗时 ai分钟,办完之后回到 A 地。但是如果他在 B 地连续待的时间大于等于 240 分钟,那么行程卡中就会显示他去过 B 地。根据 A 地的防控政策,如果去过 B 地,那么就会被隔离 7 天(10080 分钟),隔离之后才能继续正常行动(例如再启程去B 地,或者在 A 地开始正常生活)。于是他有一个对策,即在 240 分钟快到的时候就从 B 地回到 A 地,然后再去 B 地,这样 240 分钟就会重新计时,从 A 地往返一趟 B 地耗时 400 分钟。现在他在 A 地准备出发,想要在 B 地办完所有事,回 A 地开始正常生活,办 n 件事的顺序无法打乱,且办每一件事的过程中无法打断。请问他至少需要多少分钟?
输入描述:
第一行包含一个正整数 n,表示事情的个数。 接下来包含 n 个正整数,表示办每一件事所需要消耗的时间 ai。输出描述:
输出一行一个数字表示答案。示例1
输入
1 240输出
10720说明
去过 B 地的时间大于等于 240 分钟就会被隔离,所以鸡尾酒会被隔离 7 天,隔离后才能进行正常生活。所以总耗时为 400 + 240 + 10080(其中 400 是来回 B 地的时间)。注意不能将 240 分钟的事情拆解成两次来办,因为办一件事的过程不能被打断。示例2
输入
2 120 121输出
1041说明
往返一次办第一件事,再往返一次办第二件事。共耗时 400+120+400+121=1041备注:
对于 20% 的数据,有 n=1 对于 40% 的数据,有 1≤n≤2 对于另外 10% 的数据,有 240≤ai 对于 100% 的数据,有 1≤n,ai≤1000
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1010;
int a[N],n;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
int sum=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
int cnt=1;
int ans=0;
bool flag=false;
for(int i=1;i<=n;i++)
{
if(a[i]>=240)
{
flag=true;
break;
}
if(a[i]+ans>=240)
{
ans=a[i];
cnt++;
}
else
{
ans+=a[i];
}
}
if(flag)
{
cout<<10080+400+sum<<"\n";
}
else
{
cout<<min((int)(10080+400+sum),cnt*400+sum)<<"\n";
}
return 0;
}
给定三个正整数 M,N,k,对于一个正整数 x,云浅认为它是「好数」当且仅当
- M≤x≤N;
- x 在十进制下的所有位上的数字和为 k。
请你求出所有「好数」中,十进制下所有位上数字的积最大的那个。
你需要求出这个数并输出其十进制下所有位上数字的积。如果有多解,选尽可能小的 x。
数据保证有解。输入描述:
本题有多组数据。第一行一个正整数 TTT 表示数据组数。
接下来 T 行,每行三个正整数 M,N,k。输出描述:
对于每组数据,一行两个正整数,以空格隔开,分别表示你求出的 x 以及其十进制下所有位上数字的积。
示例1
输入
1 114514 191981 10输出
121222 16说明
取 x=121222,则其数字和为 1+2+1+2+2+2=10,数字积为 1×2×1×2×2×2=16。备注:
对于 100% 的数据,1≤M≤N≤5×10^6,1≤k≤100,1≤T≤100。
不得不说,这题数据是有问题
明明得到1e7,5e6就可以过, 而且1e7就炸内存,交不上。。。。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pb push_back
#define PII pair<int,int>
const int N=5e6+10;
int sum[N],ji[N];
vector<PII>G[110];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
sum[0]=0;
ji[0]=1;
for(int i=1;i<=5e6;i++)
{
sum[i]=sum[i/10]+i%10;
ji[i]=ji[i/10]*(i%10);
G[sum[i]].pb({i,ji[i]});
}
int T;
cin>>T;
while(T--)
{
int m,n,k;
cin>>m>>n>>k;
int f1=-1,f2=-1;
for(int i=0;i<G[k].size();i++)
{
int s1=G[k][i].first;
int s2=G[k][i].second;
if(s1>n||s1<m)continue;
if(s2>f2)
{
f2=s2;
f1=s1;
}
}
cout<<f1<<" "<<f2<<"\n";
}
return 0;
}
C:电梯停靠
题目描述
有一个 n 层高的楼,电梯会在 1∼n层之间运行。每次运行结束后,电梯都会自动停靠在 x 层。假设一个人想从第 5 层到第 10 层,那么电梯会先从第 x 层(因为之前已经自动停靠在 x 层了)走到第 5 层,然后从第 5 层走到第 10 层,最后再从第 10 层回到自动停靠的楼层 x 层。电梯总共会行走 ∣x−5∣+∣5−10∣+∣10−x∣ 的距离(其中 ∣x∣ 表示 x 的绝对值)
现在已知 m 个人依次乘坐电梯,每个人都会在电梯自动停靠在 x 层之后才乘坐。第 i 个人乘坐电梯是从 ai 层移动到 bi 层。现在 x 由你设置,你需要让电梯的总行走距离最短。请你输出对应的 x 和最短的行走距离。若有多个可能的 x,输出最小的一个。输入描述:
第一行包含两个正整数 n,m表示楼的层数和乘坐电梯的人数。 接下来包含 m 行,每行给出两个数字 ai,bi(ai<bi),意义如题面所示。输出描述:
输出两个数字,第一个数字表示电梯自动停靠的楼层,第二个数字表示电梯行走的最短距离。示例1
输入
10 2 3 7 4 6输出
4 12说明
电梯一开始自动停靠在位置 4,第一个人想要从第 3 层走到第 7 层。则电梯共行走 |4-3|+|3-7|+|7-4|=8。第二个人想要从第 4 层行走到第 6 层,行走之后电梯停靠回第四层,电梯共行走 8 + |4-6|+|6-4|=12。 若电梯自动停靠在 5 或 6,则总行走距离也是 12,但是对于多个可能的 x,应该输出最小值。示例2
输入
15 4 3 7 2 6 10 13 1 5输出
5 40示例3
输入
15 7 1 2 1 2 1 2 8 9 10 11 12 13 14 15输出
8 74备注:
对于 20% 的数据,有 1≤n,m≤100 对于 50% 的数据,有 1≤n,m≤2000 对于另外 20% 的数据,对于任意的 i(1≤i<m) 有 ai<bi<a(i+1)<b(i+1) 对于 100% 的数据,有 1≤n,m≤5∗10^5,1≤a,b≤n
这题更离谱,我乱搞过了。。。
正解下午补一下,这里贴一份我赛场代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e5+10;
int x[N],y[N],p[2*N];
int n,m,cnt;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// freopen("T3simple.in","r",stdin);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>x[i]>>y[i];
p[++cnt]=x[i];
p[++cnt]=y[i];
}
sort(p+1,p+1+cnt);
int sum1=0,sum2=0;
int f1=p[cnt/2];
int f2=p[cnt/2+1];
//1
for(int i=1;i<=m;i++)
{
sum1+=abs(f1-x[i])+abs(x[i]-y[i])+abs(y[i]-f1);
}
//2
for(int i=1;i<=m;i++)
{
sum2+=abs(f2-x[i])+abs(x[i]-y[i])+abs(y[i]-f2);
}
if(sum1<=sum2)
{
cout<<f1<<" "<<sum1<<"\n";
}
else
{
cout<<f2<<" "<<sum2<<"\n";
}
return 0;
}
正解:差分
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int pre[N],pre1[N],suf[N],suf1[N];
int pos=-1,ans=1e18;
int n,m,a,b,sum;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>a>>b;
pre[a-1]+=2;
suf[b+1]+=2;
sum+=(b-a)*2;
}
for(int i=n;i>=1;i--)
{
pre[i]+=pre[i+1];
pre1[i]=pre1[i+1]+pre[i];
}
for(int i=1;i<=n;i++)
{
suf[i]+=suf[i-1];
suf1[i]=suf1[i-1]+suf[i];
if(suf1[i]+pre1[i]<ans)
{
pos=i;
ans=suf1[i]+pre1[i];
}
}
cout<<pos<<" "<<ans+sum<<"\n";
return 0;
}
D:
题目描述
给定 n 个数字,第 i 个数字的大小为 ai,且它属于第 bi个集合里。在一个集合中选择一个数字,得到的价值是这个数字的大小,选择多个数字,得到的价值是这些数字的异或和。
你得到的总价值是所有集合的价值之和。你至多从中选择 m(m≤n)个数字,使得这些数字的总价值最大。输入描述:
第一行输入两个正整数 n,m(1≤n,m≤2000)n 接下来 nnn 行,每行给出两个正整数 ai,bi(1≤ai,bi≤2000)a,分别表示第 i 个数字的大小和所属集合的编号。输出描述:
输出一行一个整数表示答案示例1
输入
3 3 7 1 6 1 3 1输出
7说明
由于三个数字都在第一个集合,如果选择 6 和 7,则获得的价值为7 异或 6 = 1。只选一个数字 7 是最优的方案。示例2
输入
3 3 7 1 6 3 3 1输出
13说明
对于 1 号集合,只选一个数字 7 是最优的方案,对于 3 号集合,选择一个 6。得到的总价值为 6+7=13示例3
输入
5 3 6 1 5 1 2 1 3 3 2 3输出
10
分组背包板子题
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define int long long
const int N=2e3+10;
const int M=2e3+5;
int n,m,dp[N][N],num[N][N],dpp[N],zz[N]; //dp[i][j]表示看到第i个数,异或出j至少所需要的数字个数,num[i][j]表示第i组j个数最大的异或值
vector<int>ve[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int x,y;
cin>>x>>y;
ve[y].pb(x);
zz[y]++;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=M;j++)
{
dp[i][j]=1e9;
}
}
for(int zu=1;zu<=2000;zu++)
{
if(zz[zu]!=0) dp[1][ve[zu][0]]=1; //不加判断的话会访问越界导致运行崩溃
for(int i=2;i<=zz[zu];i++)
{
dp[i][ve[zu][i-1]]=1; //这一步很重要,不要忘记
for(int j=1;j<=M;j++)
{
if(dp[i-1][j]!=1e9)
{
dp[i][j]=min(dp[i][j],dp[i-1][j]);
dp[i][j^ve[zu][i-1]] = min(dp[i-1][j]+1,dp[i][j^ve[zu][i-1]]);
}
}
}
for(int j=1;j<=M;j++)
{
if(dp[zz[zu]][j]!=1e9) num[zu][dp[zz[zu]][j]]=max(num[zu][dp[zz[zu]][j]],j);
}
for(int i=1;i<=zz[zu];i++)
{
for(int j=1;j<=M;j++)
{
dp[i][j]=1e9;
}
}
}
for(int i=1;i<=2000;i++)
{
for(int j=m;j>=0;j--)
{
for(int k=1;k<=zz[i];k++) // 最后的枚举,只枚举到本组的个数
{
if(j>=k) dpp[j]=max(dpp[j],dpp[j-k]+num[i][k]);
}
}
}
cout<<dpp[m]<<"\n";
return 0;
}