牛客小白月赛7题解

60 篇文章 1 订阅
10 篇文章 0 订阅

没想到身为菜鸟的我也能做7题,嘿嘿嘿

2018/10/9 填坑完毕hhh

A-送分题:https://www.nowcoder.com/acm/contest/190/A

思路:该题直接交会爆内存。。。观察(跑几组数据)发现只要n大于等于2018001就都为 20182017,其他的则为 n+2017

Code :

#include<iostream>
using namespace std;

int main()
{
    long long n;
    cin >> n;
    if(n<20180001)	cout<<n+2017<<endl;
    else	cout << 20182017 << endl;
    return 0;
}

 

B-自杀游戏:https://www.nowcoder.com/acm/contest/190/B

思路:可以用dp来做,对于dp[i],只要它能够转移到必败的状态,那么dp[i]一定是必胜的,否则就是必败的

Code:

#include<iostream>
using namespace std;

const int MAX_N=100005;
int a,b,n;
int dp[MAX_N];

int main()
{
	while(cin>>n>>a>>b){
		++a;	++b;
		dp[0]=-1;
		for(int i=1;i<=n;++i)
		{
			if(dp[i-1]==-1){
				dp[i]=1;
			}else{
				if(i<a)	dp[i]=-1;
				for(int j=a;j<=b;++j)
					if(i>=j&&dp[i-j]==-1){
						dp[i]=1;	break;
					}
				if(dp[i]!=1)	dp[i]=-1;
			}
		}
		if(dp[n]==1)	cout<<"Alice"<<endl;
		else	cout<<"Bob"<<endl;
	}
	
	return 0;
}

 

C-谁是神枪手:https://www.nowcoder.com/acm/contest/190/C

思路:不难求出,对于A胜概率 Pa,B胜概率 Pb为

 B胜条件 Pb-Pa>0 最后可化为 (100-a)*b>100*a

那么平局时(100-a)*b=100*a

A胜:(100-a)*b<100*a

Code :

#include<iostream>
using namespace std;
 
int a,b;
 
int main()
{
    while(cin>>a>>b){
        if((100-a)*b>100*a)  cout<<"CSL"<<endl;
        else	if((100-a)*b==100*a)	cout<<"equal"<<endl;
        else	cout<<"MWH"<<endl;
    }
     
    return 0;
}

 

D-明七暗七:https://www.nowcoder.com/acm/contest/190/D

思路:数位DP+二分。利用数位DP可以求出从1到n的满足条件的个数,而对于求具体的数字,则可以用二分查找来求解

dp[i][j][k]: 前i位余数为j,是否有7的个数

Code :
 

#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;

LL n,m;
int a[20];
LL dp[20][10][2];

LL Find(LL p);
LL DFS(int k,int mod,int boo,int bo);
int main()
{
	ios::sync_with_stdio(false);
	while(cin>>n>>m){
		memset(dp,-1,sizeof(dp));
		LL l=n,r=1e14,t=Find(n);
		while(l<=r){
			LL h=(l+r)/2;
			if(Find(h)-t>=m)	r=h-1;
			else	l=h+1;
		}
		cout<<l<<endl;
	}
	
	return 0;
}

LL Find(LL p)
{
	int pre=0;
	while(p){
		a[pre++]=p%10;
		p/=10;
	}
	return DFS(pre-1,0,0,1);
}

LL DFS(int k,int mod,int boo,int bo)	//第k位,余数mod,boo是否有7,bo是否为p 
{
	LL ans=0;
	if(k==-1)	ans=(!mod)||boo;
	else	if(dp[k][mod][boo]!=-1&&!bo)	ans=dp[k][mod][boo];
	else{
		int pre=bo?a[k]:9;
		for(int i=0;i<=pre;++i)
			ans+=DFS(k-1,(mod*10+i)%7,boo||i==7,bo&&i==a[k]);
		if(!bo)	dp[k][mod][boo]=ans;
	}
	return ans;
}

 

E-Applese的超能力: https://www.nowcoder.com/acm/contest/190/E

思路:对于m个硬币可合成 1个硬币,最后要只剩一个硬币,由最后n=1个硬币往后推,n=1+(m-1)个硬币成立,再是1+(m-1)可当成1个硬币,则还需要6个硬币 n= 1+(m-1)+(m-1)也成立,则n=1+(m-1)*k时为Yes,否则为No

Code :

#include<iostream>
using namespace std;

int n,m;

int main()
{
	while(cin>>n>>m){
		bool boo=false;
		if(n==1||m!=1&&(n-1)%(m-1)==0)	boo=true;
		if(boo)	cout<<"Yes"<<endl;
		else	cout<<"No"<<endl;
	}
	return 0;
}

 

F-BFS:https://www.nowcoder.com/acm/contest/190/F

思路:真水题

Code:

#include<iostream>
using namespace std;

string str;

int main()
{
	while(cin>>str){
		int len=str.size();
		int boo=-1;
		for(int i=0;i<len-2;++i)
			if((str[i]=='B'||str[i]=='b')&&(str[i+1]=='O'||str[i+1]=='o')&&(str[i+2]=='B'||str[i+2]=='b')){
				boo=i;	break;
			}
		cout<<boo<<endl;
	} 
	
	return 0;
}

 

G-CSL分苹果:https://www.nowcoder.com/acm/contest/190/G

思路:背包DP,dp[i]=1表示 背包中有 i质量的苹果。则对于每个苹果质量x, 若dp[i]=1,则dp[i+x]=1;最后查找离所有苹果质量和一半sum/2最近的dp[i]=1即可

Code :

#include<iostream>
using namespace std;

const int MAX_N=100;
const int MAX_S=10005;
int n;
int dp[MAX_S];

int main()
{
	ios::sync_with_stdio(false);
	cin>>n;
	dp[0]=1;
	int sum=0;
	for(int i=1,x;i<=n;++i)
	{
		cin>>x;
		sum+=x;
		for(int j=MAX_S-x-1;j>=0;--j)
		{
			if(dp[j]){
				dp[j+x]=1;
			}
		}
	}
	int ans=0;
	for(int i=sum/2;i>=0;--i)
		if(dp[i]){
			ans=i;	break;
		}
	cout<<ans<<" "<<sum-ans<<endl; 
	
	return 0;
}

 

H-CSL的校园卡:https://www.nowcoder.com/acm/contest/190/H

思路:状态压缩DP+BFS

用dp[x1][y1][x2][y2][s]来表示两人分别在点 (x1,y1),(x2,y2)处走过的状态s时的所用时间,那么再用BFS来找到第一个满足条件的即可

Code:

#include<iostream>
#include<queue>
using namespace std;
 
struct node{
    int x1,y1;
    int x2,y2;
    int t,s;
};
const int MAX_S=(1<<16)+5;
const int f[][2]={-1,0, 1,0, 0,-1, 0,1};
int n,m,ans,Sum;
string G[5];
bool boo[5][5][5][5][MAX_S];
 
void BFS(int x,int y);
int main()
{
    cin>>n>>m;
    int x0,y0;
    for(int i=0;i<n;++i)
    {
        cin>>G[i];
        for(int j=0;j<m;++j)
            if(G[i][j]=='S'){
                x0=i;   y0=j;
                Sum+=(1<<(i*4+j));
            }else   if(G[i][j]=='O'){
                Sum+=(1<<(i*4+j));
            }
    }
    BFS(x0,y0);
    cout<<ans<<endl;
    return 0;
}
 
void BFS(int x,int y)
{
    queue<node> Q;
    Q.push(node{x,y,x,y,1<<(x*4+y),0});
    boo[x][y][x][y][(1<<(x*4+y))]=1;
    while(!Q.empty()){
        int x1,y1,x2,y2;
        node u=Q.front();   Q.pop();
        for(int i=0;i<4;++i)
        {
            x1=u.x1+f[i][0];    y1=u.y1+f[i][1];
            int t1=1<<(x1*4+y1);
            if(x1>=0&&x1<n&&y1>=0&&y1<m&&G[x1][y1]!='X'){
                for(int j=0;j<4;++j)
                {
                    x2=u.x2+f[j][0];    y2=u.y2+f[j][1];
                    int t2=1<<(x2*4+y2);
                    if(x2>=0&&x2<n&&y2>=0&&y2<m&&G[x2][y2]!='X'){
                        int s=(t1|t2)|u.t;
                        if(!boo[x1][y1][x2][y2][s]){
                            Q.push(node{x1,y1,x2,y2,s,u.s+1});
                            boo[x1][y1][x2][y2][s]=1;
                        }
                        if(s==Sum){
                            ans=u.s+1;
                            return;
                        }
                    }
                }
            }
        }
    }
}

 

I-新建 Microsoft Office Word 文档:https://www.nowcoder.com/acm/contest/190/I

思路:利用优先队列Q来维护最小值,同时用数组boo[]来对已有文档序列做标记即可

Code:

#include<iostream>
#include<queue>
using namespace std;

const int MAX_N=100005;
int n,T;
string str;
priority_queue<int,vector<int>,greater<int> > Q;
bool boo[MAX_N];

int main()
{
	cin>>T;
	n=0;
	int x;
	while(T--){
		cin>>str;
		if(str=="New"){
			if(!Q.empty()){
				cout<<Q.top()<<endl;
				boo[Q.top()]=true;
				Q.pop();
			}else{
				boo[++n]=true;
				cout<<n<<endl;
			}
		}else{
			cin>>x;
			if(boo[x]){
				boo[x]=false;
				Q.push(x);
				cout<<"Successful"<<endl;
			}else	cout<<"Failed"<<endl;
		}
	}
	
	return 0;
}

 

J-方格填色:https://www.nowcoder.com/acm/contest/190/J

思路:状态压缩+矩阵快速幂

对于状态压缩方程易得转换方程

for(int i=2;i<=n;++i)
	for(int j=0;j<=s;++j)
		for(int k=0;k<=s;++k)
			if((j||k)&&!(j&k))	dp[i][j]=(dp[i][j]+dp[i-1][k])%MOD;

而对于转移方程可以用矩阵快速幂来优化,与骨牌覆盖类似https://blog.csdn.net/C_13579/article/details/82883625

Code :

#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;

const int MOD=1e9+7;
const int MAX_S=35;
struct Matrix{
	LL a[MAX_S][MAX_S];
	Matrix(){memset(a,0,sizeof(a));}
	Matrix operator*(const Matrix &A){
		Matrix res=Matrix();
		for(int k=0;k<MAX_S;++k)
			for(int i=0;i<MAX_S;++i)
				for(int j=0;j<MAX_S;++j)
					res.a[i][j]=(res.a[i][j]+a[i][k]*A.a[k][j]%MOD)%MOD;
		return res;
	}
};
LL n,m;

int main()
{
	ios::sync_with_stdio(false);
	while(cin>>m>>n){
		int s=(1<<m)-1;
		Matrix t0=Matrix(),ans=Matrix();
		for(int i=0;i<MAX_S;++i)
			ans.a[i][i]=1;
		for(int i=0;i<=s;++i)
			for(int j=0;j<=s;++j)
				if((i||j)&&!(i&j))	t0.a[i][j]=1;
		--n;
		while(n){
			if(n&1)	ans=ans*t0;
			t0=t0*t0;
			n>>=1;
		}
		LL res=0;
		for(int i=0;i<=s;++i)
			for(int j=0;j<=s;++j)
				res=(res+ans.a[i][j])%MOD;
		cout<<res<<endl;
	}
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值