牛客挑战赛59
木桩:
链接:https://ac.nowcoder.com/acm/contest/11199/A
分析:首先考虑一个小木桩前有x个大木桩 后有y个大木桩
则这个小木桩的贡献就是x×y-x 很明显均值不等式得到x和y尽量均分才能答案最大
如果a为偶数那么恰好前后各一半
如果a为奇数那么多的那一个放在后面一定最优
code:
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
int T;
void solve();
int main(){
cin>>T;
while(T--)solve();
return 0;
}
void solve(){
ll a,b;
scanf("%lld%lld",&a,&b);
ll t1=a/2;
ll t2=t1;
if(a%2)t2++;
cout<<b*(t2-1)*t1<<endl;
}
游戏:
链接:https://ac.nowcoder.com/acm/contest/11199/B
分析:
假设第i个人获胜
因为要求每一个人的获胜概率
所以首先要求出直到前i-1轮是 剪刀/石头/步 获胜的概率(谁获胜的不重要 重要的是三者中哪个在前一轮胜出)
这个直接转移就好了
接下来几轮就只能第i个人获胜 所以这样倒着转移就好了
总结一下 本题的核心在与 前i-1轮是谁输赢不重要 只用关注是石头/剪刀/步 在第i-1轮胜出 后面几轮第i个人都必须赢
code:
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int mod=998244353;
const int maxn=1e5+7;
ll dp[maxn][3],f[3],ans[maxn],t[3],ni[maxn];
int n;
int a[maxn][3],cnt[maxn];
ll ksm(ll aa,ll bb){
ll res=1;
while(bb){
if(bb&1)res=res*aa%mod;
bb>>=1;
aa=aa*aa%mod;
}
return res;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int tot=0;
for(int j=0;j<3;j++){
scanf("%1d",&a[i][j]);
if(a[i][j]==1)tot++;
}
cnt[i]=tot;
}
for(int i=1;i<=n;i++)ni[i]=ksm(cnt[i],mod-2);
for(int i=0;i<3;i++)
if(a[1][i]==1)
dp[1][i]=ni[1];
for(int i=2;i<=n;i++)
for(int j=0;j<3;j++)
dp[i][j]=(dp[i-1][j]*(a[i][j]+a[i][(j+1)%3])%mod+dp[i-1][(j+1)%3]*a[i][j])%mod*ni[i]%mod;
for(int i=0;i<3;i++)
if(a[n][i]==1)
t[i]=(t[i]+ni[n])%mod,t[(i-1+3)%3]=(t[(i-1+3)%3]+ni[n])%mod;
for(int i=0;i<3;i++)
f[i]=t[i];
ll tt=0;
for(int i=0;i<3;i++)
if(a[n][i]==1)
tt=(tt+dp[n-1][(i+1)%3]*ni[n]%mod)%mod;
ans[n]=tt;
for(int i=0;i<3;i++)
dp[0][i]=1;
for(int i=n-1;i>=1;i--){
ll tt=0;
for(int j=0;j<3;j++)
if(a[i][j]==1)
tt=(tt+dp[i-1][(j+1)%3]*ni[i]%mod*f[j]%mod)%mod;
t[0]=t[1]=t[2]=0;
for(int j=0;j<3;j++)
if(a[i][j]==1)
t[j]=(t[j]+ni[i])%mod,t[(j-1+3)%3]=(t[(j-1+3)%3]+ni[i])%mod;
for(int j=0;j<3;j++)
f[j]=f[j]*t[j]%mod;
ans[i]=tt;
}
for(int i=1;i<=n;i++)
cout<<ans[i]<<" ";
return 0;
}
异或

分析:
相较于一般的线性基多了一个奇数偶数的限制
那怎么办呢?
针对偶数 将原数组a变为b[i]=a[i]^a[i+1]
针对奇数 将原数组a变为b[i]=a[i]^(2的inf次方)
不得不说真的太巧妙了 学到了
还有就是要用到bitset 用法我以前有写过https://zhuanlan.zhihu.com/p/578274936
#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=2005;
bitset<maxn>a[maxn],b[maxn],x[maxn],p[maxn],ans,mm;
int n;
void insert(bitset<maxn>t){
for(int i=maxn-1;i>=0;i--){
if((t>>i)==0)continue;
if(!p[i].count()){p[i]=t;break;}
else t^=p[i];
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)cin>>x[i];
for(int i=1;i<n;i++)insert(x[i]^x[i+1]);
insert(x[n]^x[1]);
for(int i=maxn-1;i>=0;i--)
if(!ans[i])ans^=p[i];
int pos=maxn-1;
while(!ans[pos]&&pos)pos--;
while(pos>=0)cout<<ans[pos--];
cout<<endl;
ans.reset();mm.set(maxn-1);
for(int i=0;i<maxn;i++)p[i].reset();
for(int i=1;i<=n;i++)insert(x[i]^mm);
for(int i=maxn-1;i>=0;i--)
if(!ans[i])ans^=p[i];
pos=maxn-2;
while(!ans[pos]&&pos)pos--;
while(pos>=0)cout<<ans[pos--];
cout<<endl;
return 0;
}

浙公网安备 33010602011771号