B:Rinne Loves Xor
题目就是要你求所有的从1到n,bi异或aj,j<=i,ai异或bj,j<=i。这样理解比题目说的从加上上次好想一点,因为是异或这种关系我们很容易就要想到二进制从二进制着手,把所有位数出现了多少个0和出现了多少个1统计下就行了,然后算下当前位的a的0和b的1有多少种搭配方法和b的0和a的1有多少搭配方法,再乘上当前的位子对应的权值即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read(){
int s=0,f=1;char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;c=getchar();
}
while(c>='0'&&c<='9'){
s=(s<<1)+(s<<3)+(c^48);c=getchar();
}
return f*s;
}
const int N=1555555,mod=1e9+7;
ll a[N],b[N],s[N][2],A[N][2],B[N][2];
int main(){
int n=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++)b[i]=read();
for(int i=1;i<=n;i++){
ll ans=0;
for(int j=0;j<=31;j++){
A[j][(1<<j&a[i])?1:0]++;//统计a和b在当前位有多少个0和1
B[j][(1<<j&b[i])?1:0]++;
ans+=A[j][0]*B[j][1]+A[j][1]*B[j][0]<<j;
ans%=mod;
}
printf("%lld ",ans);
}
return 0;
}C:阶乘
题目很容易理解,主流的解题方式都是二分,我这介绍一种打表的方法。
首先存下sqrt(1e9)以内的素数有哪些,然后对于我们要求的那个数,我们因数分解后剩下的最大的素数的多少次方那个数就是答案,思路不难,剩下看代码如何处理。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read(){
ll s=0,f=1;char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;c=getchar();
}
while(c>='0'&&c<='9'){
s=(s<<1)+(s<<3)+(c^48);c=getchar();
}
return f*s;
}
const int N=1555555,m=(1<<30);
int a[N];
bool vis[N];
vector<int>q,v[N];
int main(){
for(int i=2;i<=100000;i++){//欧拉筛素数
if(vis[i])continue;
q.push_back(i);
for(int j=i;j<=100000;j+=i){
vis[j]=true;
}
}
for(int i=0;i<q.size();i++){//提前存好素数^n的值是多少
v[i].push_back(0);
int num=1,t=q[i];
while(num<=30){
int x=t;
while(x%q[i]==0&&x){
v[i].push_back(t);num++;x/=q[i];
}
t+=q[i];
}
}
int T=read();
while(T--){
int n=read(),ans=0;
for(int i=0;i<q.size();i++){
int num=0;
while(n%q[i]==0&&n){//因数分解,取最大的因数分解后的值
n/=q[i];
num++;
}
ans=max(ans,v[i][num]);
}
ans=max(ans,n);
printf("%d\n",ans);
}
}D:小石的签到题
看下过题的人数,这题好像并没有想的那么复杂。于是乎暴力枚举下3,4,5,6,7,8的情况,果断猜测1先手输,否则先手必胜。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read(){
int s=0,f=1;char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;c=getchar();
}
while(c>='0'&&c<='9'){
s=(s<<1)+(s<<3)+(c^48);c=getchar();
}
return f*s;
}
int main(){
int n=read();
if(n==1)cout<<"Yang"<<endl;
else cout<<"Shi"<<endl;
return 0;
}E:装备合成
这题好像也都是二分写的,但是咱不信邪用数学方法写了出来。
思路是贪心,假设先把所有零件都用来做y装备,做2件x装备和做1件y装备的a类材料需求一样,b类材料需求是2件a比1件b多5个,所以我们先全部做y装备,然后每多5个b类材料就能把1件y装备换成2件x装备,注意考虑下特殊情况,单独多出个2的情况以及b材料就算全部做y装备也不够配。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read(){
ll s=0,f=1;char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;c=getchar();
}
while(c>='0'&&c<='9'){
s=(s<<1)+(s<<3)+(c^48);c=getchar();
}
return f*s;
}
const int N=1555555;
int main(){
ll T;scanf("%lld",&T);
while(T--){
ll x=read(),y=read();
ll ans=x/4,v=0;y-=ans;
if(x%4>=2&&y>=3){
v=1;y-=3;
}
if(y<=0)ans+=y;
else{
ans+=min(ans,y/5);
}
cout<<ans+v<<endl;
}
return 0;
}
京公网安备 11010502036488号