版权声明:欢迎转载,转载请注明出处,如有错误,还望指出,谢谢 博客地址:https://blog.csdn.net/lanyanzhiji123asd https://blog.csdn.net/lanyanzhiji123asd/article/details/89280079
比赛链接:https://ac.nowcoder.com/acm/contest/549#question
A :
通过已经给的代码,打表找规律,偶数输出-1,奇数输出1
#include<bits/stdc++.h>
using namespace std;
int main() {
long long n;
while(~scanf("%lld",&n))
{
if(n%2==0)cout<<"-1"<<endl;
else cout<<"1"<<endl;
}
return 0;
}
C: 概率问题吧,买n张彩票一共有4^n次方方案,然后我们再算出不亏本的方案数
不亏本的方案数有两种方法,一种是直接暴力,数据范围只有30
第二种方法就是动态规划
dp[ i ][ j ]表示第 i 张彩票得到 j 元的方案数
然后如果n等于0 概率是1
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
#define ll long long
ll dp[35][125];
ll gcd(ll a, ll b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
void huaj(ll *a, ll *b)
{
ll temp=gcd((*a),(*b));
(*a)/=temp;
(*b)/=temp;
}
int main()
{
std::ios::sync_with_stdio(false);
int i,j,k,n;
while(cin>>n)
{
if(n==0)
{
cout<<"1/1"<<endl;
continue;
}
memset(dp,0,sizeof(dp));
dp[1][1]=1;
dp[1][2]=1;
dp[1][3]=1;
dp[1][4]=1;
for(i=2;i<=n;i++)
{
for(j=i;j<=4*i;j++)
{
for(k=1;k<=4;k++)
{
dp[i][j]+=dp[i-1][j-k];
}
}
}
ll ans=0,par=1;
for(i=3*n;i<=4*n;i++)
{
ans+=dp[n][i];
}
// cout<<ans<<endl;
if(ans==0)
{
cout<<"0/1"<<endl;
}
else
{
for(i=1;i<=n;i++)
{
par*=4;
}
// cout<<par<<endl;
huaj(&ans,&par);
cout<<ans<<"/"<<par<<endl;
}
}
return 0;
}
D : 前缀或和后缀或
因为或运算与顺序无关
所以我分别用两个数组维护前缀或和后缀或,然后枚举每个数
最后求出最大值
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
#define ll long long
ll mp[5000005],qianz[5000005],houz[5000006];
int main()
{
std::ios::sync_with_stdio(false);
int n,i;
ll ans=-0x3f3f3f3f3f3f3f3f,temp;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>mp[i];
}
qianz[0]=0;
houz[n+1]=0;
qianz[1]=mp[1];
houz[n]=mp[n];
for(i=2;i<=n;i++)
{
qianz[i]=qianz[i-1]|mp[i];
}
for(i=n-1;i>0;i--)
{
houz[i]=houz[i+1]|mp[i];
}
for(i=1;i<=n;i++)
{
temp=qianz[i-1]|houz[i+1];
ans=max(ans,temp);
}
cout<<ans<<endl;
return 0;
}
G:双向BFS
看了一下别人的代码
用一个队列维护,但是每个入队的点都要标记这个点是从小A走到的还是小B走到的
然后每次判断下如果这个点是小A走到的 但是小B已经走过了,或者这个点是小B走到的,但是小A已经走过了。
用vis数组标记这个点曾经被谁走过
需要注意的是,小B每次是可以走两步的,所以相当于小B走了两步,但是时间花了一秒,小A走了一步,时间花了一秒
所以入队的时候需要注意下
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
#define ll long long
int d[8][2]={0,-1,-1,0,0,1,1,0,-1,-1,-1,1,1,-1,1,1};
struct node
{
int x,y,id,step;
};
queue<node>q;
int n,m;
char mp[1005][1005];
int vis[1005][1005];
int access(int x,int y)
{
if(x<=n&&x>0&&y<=m&&y>0&&mp[x][y]=='.'&&!vis[x][y])
return 1;
return 0;
}
int BFS()
{
int up,i,j;
while(!q.empty())
{
node v=q.front();
q.pop();
if(v.id==1)
{
up=8;
for(i=0;i<up;i++)
{
int xx=v.x+d[i][0];
int yy=v.y+d[i][1];
if(vis[xx][yy]==2)return v.step+1;
if(access(xx,yy))
{//cout<<xx<<" "<<yy<<" "<<mp[xx][yy]<<endl;
q.push((node){xx,yy,1,v.step+1});
vis[xx][yy]=1;
}
}
}
else
{
up=4;
for(i=0;i<up;i++)
{
int xx=v.x+d[i][0];
int yy=v.y+d[i][1];
if(vis[xx][yy]==1)return v.step+1;
if(access(xx,yy))
{
vis[xx][yy]=2;
for(j=0;j<up;j++)
{
int xxx=xx+d[j][0];
int yyy=yy+d[j][1];
if(vis[xxx][yyy]==1)return v.step+1;//这里需要注意
if(access(xxx,yyy))
{
q.push((node){xxx,yyy,2,v.step+1});//这里需要注意
vis[xxx][yyy]=2;
}
}
}
}
}
}
return -1;
}
int main()
{
std::ios::sync_with_stdio(false);
int i,j;
while(cin>>n>>m)
{
while(!q.empty())
q.pop();
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cin>>mp[i][j];
if(mp[i][j]=='C')
{
q.push((node){i,j,1,0});
}
if(mp[i][j]=='D')
{
q.push((node){i,j,2,0});
}
}
}
int ans=BFS();
if(ans==-1)
cout<<"NO"<<endl;
else
{
cout<<"YES"<<endl;
cout<<ans<<endl;
}
}
return 0;
}