https://codeforces.com/contest/1610/problem/C
题意:有n个人,富裕程度1~n, 要举行派对,要求对于每个人,来的人中比他富的不超过
a
i
a_i
ai, 比他穷的不超过
b
i
b_i
bi,问最多能邀请多少人来.
思路:二分答案,把答案最大化。关键是怎么统计能邀请多少人,假设可以邀请mid人,对于每个人,记录当前已经邀请了cnt人,如果
b
i
b_i
bi>=cnt,并且
a
i
a_i
ai>=mid-cnt-1, 那么说明可以邀请这个人。
code :
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
const int N=2e5+10;
int a[N],b[N];
int n;
bool check(int mid)//mid为答案选几个
{
int cnt=0;//当前选了cnt个
for(int i=1;i<=n;i++){
if(b[i]>=cnt&&a[i]>=mid-cnt-1) cnt++;
}
if(cnt>=mid) return 1;
return 0;
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
}
int l=1,r=n;
while(l<r)
{
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<r<<endl;
}
signed main()
{
ios;
int t;
cin>>t;
//t=1;
while(t--)
{
solve();
}
return 0;
}
题目大意:给定一个序列 a ,a为未知序列,长度为n,给m个已知信息,为从 a l a_l al 到 a r a_r ar 的或的值为x, 求a的所有子集中元素异或值的和。
思路:对二进制下每一位分析,就比如对于每个元素的第3位,构成一个集合b,b={b1,b2,b3,…bn}, 对于某个 b i b_i bi, 若 b i b_i bi 为1,则将集合分为含有 b i b_i bi和不含 b i b_i bi的两种集合,其数量均为 2 n − 1 2^{n-1} 2n−1个,其异或值为1的一定在这两个集合的其中一个,因此每一位1的贡献为 :当前1对应的值 * 2 n − 1 2^{n-1} 2n−1, 那么怎么判断当前位是否有1呢?直接将所有x或起来即可。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
//head
typedef pair<int,int> pii;
const int N=2e5+10,mod=1e9+7;
int qmi(int a,int k)
{
int ans=1;
while(k)
{
if(k&1) ans=(ans*a)%mod;
a=(a*a)%mod;
k>>=1;
}
return ans;
}
void solve()
{
int n,m;
cin>>n>>m;
int ans=0;
while(m--)
{
int l,r,x;
cin>>l>>r>>x;
ans|=x;
}
cout<<ans*qmi(2,n-1)%mod<<endl;
}
signed main()
{
ios;
int t;
cin>>t;
while(t--)
{
solve();
}
return 0;
}
题目大意 : 将长度为n的序列a,(初始全为1),最多经过k次变化,能获得的最大值是多少。每次变化操作为: a i a_i ai+= a i a_i ai/x;将 a i a_i ai 变为 b i b_i bi 可以获得 c i c_i ci 的值。
思路:01背包求解,预处理出来每个 a i a_i ai 变为 b i b_i bi 的最小次数, 以该次数为体积,以 c i c_i ci 为价值做一遍01背包即可。需要注意的是每个数最大变化次数不超过12次,而k值较大,因此在求体积时要与k取 min。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
const int N=1e5+10;
int b[N],w[N],v[N];
int n,k;
int f[N],cnt[100010];
void solve()
{
memset(f,0,sizeof f);
cin>>n>>k;
int sum=0;
for(int i=1;i<=n;i++) cin>>b[i];
for(int i=1;i<=n;i++) cin>>w[i];
for(int i=1;i<=n;i++) {
v[i]=cnt[b[i]];
sum+=v[i];
}
k=min(k,sum);
for(int i=1;i<=n;i++){
for(int j=k;j>=v[i];j--){
f[j]=max(f[j-v[i]]+w[i],f[j]);
}
}
cout<<f[k]<<endl;
}
signed main()
{
memset(cnt,0x3f,sizeof cnt);
cnt[1]=0;
for(int i=1;i<=1e3;i++){
for(int j=1;j<=i;j++){
cnt[i+(i/j)]=min(cnt[i+(i/j)],cnt[i]+1);
}
}
//ios;
int t;
cin>>t;
//t=1;
while(t--)
{
solve();
}
return 0;
}