2024牛客寒假算法基础集训营1个人补题题解(I、H)
比赛链接:2024牛客寒假算法基础集训营1
过年被拖到亲戚家了,剩下的题回头再补
I、It's bertrand paradox. Again!
这么抽象的东西出得很好,下次别再出了。
从bit和buaa不同的抽数规则可以得出一个结论:bit抽取具体坐标点的次数会明显小于buaa,甚至只有在几乎不可能的理想范围内两者抽取的次数才相近,因此因为样本量极大(1e5次),bit抽取的点在整个坐标轴内的分布会更加均匀。可以将整个二维平面画出一个由\(x\)轴和\(y\)轴的范围都分别是\([-99,99]\)的长宽均是\(199\)的矩形框,每次抽取一个\((x,y)\)坐标时,矩形框内每个点被抽取到的概率为\(\frac{1}{199*199}\)。
现在我们要确定一份生成的坐标表是属于谁的,可以在这个大矩形框内分出一个小矩形框,例如选择\(x\)轴和\(y\)轴的范围都分别是\([-60,60]\)的长宽均是\(121\)的矩形框,每次抽取的点出现在这个框内的概率是\(\frac{121*121}{199*199}\)那么\(10^5\)次抽取后落在这个矩形框内的理想数量就是\(\frac{121*121}{199*199}*10^5=36,971\)个,如果是抽取数量只可能更多的buaa那实际数量只会比这个多或少,统计一下在设定方框内的点的数量和一个差值,如果在容错范围内就是bit的,否则就是buaa的。
实测这个差值可以随便选,500能过,1000能过,2000能过,5000也能过(
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
const int inf=1e18;
const int M=1e9+7;
signed main() {
int t;
cin >>t;
int cnt=0;
double k=(121.0*121.0)/(199.0*199.0)*1e5;
while(t--)
{
int x,y,r;
cin >>x>>y>>r;
if(x>=-60&&x<=60&&y>=-60&&y<=60)
cnt++;
}
if(fabs(cnt-k)>=500)
cout<<"buaa-noob"<<'\n';
else cout<<"bit-noob"<<'\n';
return 0;
}
H、01背包,但是bit
贪心考虑。如果二进制数\(a\)小于二进制数\(b\),必有至少一位满足\(b\)中为\(1\)但\(a\)中为\(0\)。枚举最靠前的这个不相等位。
做法:将\(m\)拆位,当\(m\)某位对应为\(1\)时将该位置\(0\),后面全填\(1\),把所有重量和这个新得到的数取或,如果还是等于这个数本身就表示可以该物品在该情况下可以取。
特判考虑选的所有数或起来恰好等于m的情况。
所有情况的价值取最大值。
AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
const int inf=1e18;
const int M=1e9+7;
int w[N];
int v[N];
int quick(int a,int b)
{
int ans=1;
while(b)
{
if(b&1)
ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
signed main() {
int t;
cin>>t;
while(t--)
{
int n,m;
int ans=0;
cin >>n>>m;
for(int i=1;i<=n;i++)
cin >>v[i]>>w[i];
for(int i=0;i<=32;i++)
{
if((m>>i)&1)
{
int k=((m>>(i+1))<<(i+1))+quick(2,i)-1;
int now=0;
for(int j=1;j<=n;j++)
{
if((k|w[j])==k)
now+=v[j];
}
ans=max(now,ans);
}
}
int cnt=0;
for(int i=1;i<=n;i++)
{
if((w[i]|m)==m)
cnt+=v[i];
}
ans=max(cnt,ans);
cout<<ans<<'\n';
}
return 0;
}

浙公网安备 33010602011771号