A
题意:
- n个物品各有一个价格,不买小于l和大于r的,有k块钱,最多可以买几件?
思路:
- 去掉不买的从小到大排个序,买到不能买为止。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; cin>>T;
while(T--){
int n, l, r, k; cin>>n>>l>>r>>k;
vector<int>vc;
for(int i = 1; i <= n; i++){
int x; cin>>x;
if(x>=l && x<=r)vc.push_back(x);
}
sort(vc.begin(),vc.end());
int ans = 0;
for(int x: vc){
//cout<<x<<"\n";
if(k >= x){
ans++; k -= x;
}else{
break;
}
}
cout<<ans<<"\n";
}
return 0;
}
B
题意:
- 数轴上需要摆放一共n+1个点,两点距离为差的绝对值。
- 从0号点出发到其他n个点分别来回走ai次,求总距离最小的点摆放方案。
思路:
- 0号点放在0,剩下的点按照需要走的次数从大到小排序,依次在0号点一左一右摆放上去即可。
- 记得开longlong不然会WA4
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn = 1e5+10;
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
LL T; cin>>T;
while(T--){
LL n; cin>>n;
vector<pair<LL,LL> >vc;
for(LL i = 1; i <= n; i++){
LL x; cin>>x;
vc.push_back(make_pair(x,i));
}
sort(vc.begin(),vc.end());
vector<LL>p(n+1);
p[0] = 0;
LL l = -1, r = 1, ans = 0;
for(LL i = vc.size()-1; i >= 0; i--){
if(i%2==0){
p[vc[i].second] = l;
ans += abs(0-l)*2*vc[i].first;
l--;
}else{
p[vc[i].second] = r;
ans += abs(r-0)*2*vc[i].first;
r++;
}
}
cout<<ans<<"\n";
for(LL i = 0; i <= n; i++){
cout<<p[i]<<" ";
}
cout<<"\n";
}
return 0;
}
C
题意:
- 长为n的数组,给出m对l,r,x,表示a[l] 按位或 a[l+1] … 按位或a[r]的值为x。
- 求原数组所有子序列按位异或和的总和。
思路:
- 依次考虑每一位的贡献,如果存在该位为1,那么互相异或后,不管出现多少次,都会产生pows(2,i-1)的贡献。如果全or也是0,那么最后贡献肯定也是0。
- 所以结论为pows(2,n-1)*所有x异或后的数。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
const int mod = 1e9+7;
LL pows(LL a, LL x, LL p){if(x==0)return 1; LL t = pows(a, x>>1,p);if(x%2==0)return t*t%p;return t*t%p*a%p;}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; cin>>T;
while(T--){
int n, m; cin>>n>>m;
int ans = 0;
for(int i = 1; i <= m; i++){
int l, r, x; cin>>l>>r>>x;
ans |= x;
}
ans = ans*pows(2,n-1,mod)%mod;
cout<<ans<<"\n";
}
return 0;
}
D1
题意:
- 给出一个长为n的序列,求构造一种排序方式,让
的值最大,输出这个值。
思路:
- 令s[i]表示a中第i个数的倍数有几个,dp[i]表示以第i个数开头的最大值。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 5e6+10;
LL s[maxn], dp[maxn];
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n; cin>>n;
for(int i = 1; i <= n; i++){
int x; cin>>x; s[x]++;
}
for(int i = 1; i < maxn; i++){
for(int j = 2*i; j < maxn; j+=i){
s[i] += s[j];
}
}
LL ans = 0;
for(int i = maxn-5; i >= 1; i--){
dp[i] += s[i]*i; //这s[i]个数都会与a[i]产生大小为a[i]的公因数
for(int j = 2*i; j < maxn; j+=i){//枚举a[i]的所有倍数
dp[i] = max(dp[i], dp[j]+(s[i]-s[j])*i);
}
ans = max(ans, dp[i]);
}
cout<<ans<<"\n";
return 0;
}