牛客寒假基础训练营3

牛客寒假基础训练营3


A:牛牛的DRB迷宫I

一道记忆话搜索题,对于一个点(x,y)考虑(x-1,y)和(x,y-1),根据是否允许移动进行更新,如果(x-1,y)不等于'R'则(x,y)位置加上(x-1,y)处的值,如果(x,y-1)处不等于'D'则(x,y)处加上(x,y-1)处的值,一直这样更新下去,注意取模就可以了。

/*************************************************
* @Author: maple
* @Date:   2020-02-08 12:12:02
* @Last Modified by:   maple
* @Last Modified time: 2020-02-08 13:10:23
* @Mark	
*************************************************/
#include <bits/stdc++.h>
#define CSE(x,y) memset(x,y,sizeof(x))
#define lowbit(x) x&(-x)
#define FAST ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x3f3f3f3f
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const int maxn=111;

ll mp[maxn][maxn],n,m;
char ss[maxn][maxn];
ll mod=1e9+7;

int main()
{
	FAST;
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	#endif
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>ss[i];
	}
	CSE(mp,0);
	mp[0][0]=1;
	for(int i=1;i<m;i++){
		if(ss[0][i-1]!='D')
			mp[0][i]=(mp[0][i]+mp[0][i-1])%mod;
	}
	for(int i=1;i<n;i++){
		if(ss[i-1][0]!='R')
			mp[i][0]=(mp[i][0]+mp[i-1][0])%mod;
	}
	for(int i=1;i<n;i++){
		for(int j=1;j<m;j++){
			if(ss[i-1][j]!='R')
				mp[i][j]=(mp[i][j]+mp[i-1][j])%mod;
			if(ss[i][j-1]!='D')
				mp[i][j]=(mp[i][j]+mp[i][j-1])%mod;
		}
	}
	cout<<mp[n-1][m-1]%mod<<endl;
	return 0;
}

B:牛牛的DRB迷宫II


C:牛牛的数组越位

这个题写法应该很多,我是选择了把二维座标直接转化为一维座标,如果转化成一维出现越界那么就是RE,如果转换成一维座标没有问题就是AC且在二维座标下没有问题,如果二维座标下有问题,那么就是UB了。

/*************************************************
* @Author: maple
* @Date:   2020-02-08 13:37:12
* @Last Modified by:   maple
* @Last Modified time: 2020-02-08 13:55:13
* @Mark	
*************************************************/
#include <bits/stdc++.h>
#define CSE(x,y) memset(x,y,sizeof(x))
#define lowbit(x) x&(-x)
#define FAST ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x3f3f3f3f
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const int maxn=1111111;

int arr[maxn],n,m,p;

int main()
{
	FAST;
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	#endif
	int t;
	cin>>t;
	while(t--){
		CSE(arr,0);
		bool ub=false,re=false;
		cin>>n>>m>>p;
		for(int i=0;i<p;i++){
			int x,y,val;
			cin>>x>>y>>val;
			if(x<0||y<0||x>=n||y>=m){
				if(1ll*x*m+y<0||1ll*x*m+y>=1ll*n*m){
					re=true;
				}
				else{
					arr[x*m+y]=val;
					ub=true;
				}
			}
			else{
				arr[x*m+y]=val;
			}
		}
		if(re){
			cout<<"Runtime error"<<endl;
		}
		else{
			for(int i=0;i<n;i++){
				for(int j=0;j<m;j++){
					if(j!=0) cout<<" ";
					cout<<arr[i*m+j];
				}
				cout<<endl;
			}
			if(ub){
				cout<<"Undefined Behaviour"<<endl;
			}
			else
				cout<<"Accepted"<<endl;
		}
	}
	return 0;
}

D:牛牛与二叉树的数组存储

这题只是简单介绍了一下二叉树的结构和线性存储,可以理解成把一颗二叉树的根存到1处之后其左子树座标为i*2其右子树座标为i*2+1,由此存储这颗树,没有节点的位置为-1,根据这个规律,我们只需要统计不为-1的个数即为数的节点个数也就是尺寸,之后根节点就是1处的值,然后对于每一个不为-1的点我们用数组记录,这个点的父节点是谁和其左右儿子分别是谁,之后按要求输出就可了,虽然说起来可能有点乱,但是看代码就很容易明白了。

/*************************************************
* @Author: maple
* @Date:   2020-02-08 14:31:43
* @Last Modified by:   maple
* @Last Modified time: 2020-02-08 14:40:31
* @Mark	
*************************************************/
#include <bits/stdc++.h>
#define CSE(x,y) memset(x,y,sizeof(x))
#define lowbit(x) x&(-x)
#define Abs(x) x>=0?x:(-x)
#define FAST ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x3f3f3f3f
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const int maxn=333333;

int tree[maxn],n;
int father[maxn],lchild[maxn],rchild[maxn];

int main()
{
	FAST;
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	#endif
	CSE(tree,-1);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>tree[i];
	}
	int size=0;
	for(int i=1;i<=n;i++){
		if(tree[i]!=-1){
			size++;
			father[tree[i]]=tree[i/2];
			lchild[tree[i]]=tree[i*2];
			rchild[tree[i]]=tree[i*2+1];
		}
	}
	cout<<"The size of the tree is "<<size<<endl;
	cout<<"Node "<<tree[1]<<" is the root node of the tree"<<endl;
	for(int i=1;i<=size;i++){
		printf("The father of node %d is %d, the left child is %d, and the right child is %d\n",i,father[i],lchild[i],rchild[i]);
	}
	return 0;
}

E:牛牛的随机数


这题我们可以去考虑前缀的方法去考虑这个问题,我们计算出每一个值它前面和它组成link的点所产生的能量之和,当遍历到下一个link点时,这个点处的结果为前一个link点的值加上上一个link点到这个link点的距离乘以之前link点的个数即可算出该点存在所产生的link值,最后遍历数组把所有能量值加起来就可以了。

/*************************************************
* @Author: maple
* @Date:   2020-02-08 13:55:56
* @Last Modified by:   maple
* @Last Modified time: 2020-02-08 14:21:48
* @Mark	
*************************************************/
#include <bits/stdc++.h>
#define CSE(x,y) memset(x,y,sizeof(x))
#define lowbit(x) x&(-x)
#define Abs(x) x>=0?x:(-x)
#define FAST ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x3f3f3f3f
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const int maxn=111111;
const ll  mod = 1e9+7;

ll arr[maxn],num=0,len=0,n,last=0;
string str;

int main()
{
	FAST;
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	#endif
	cin>>n>>str;
	for(int i=0;i<n;i++){
		if(str[i]=='1'){
			arr[i]=(last+num*len%mod)%mod;
			num++;
			len=0;
			last=arr[i];
		}
		len++;
	}
	ll ans=0;
	for(int i=0;i<n;i++){
		if(str[i]=='1')
			ans=(ans+arr[i])%mod;
	}
	cout<<ans<<endl;
	return 0;
}


H:牛牛的k合因子

先说我是怎么想的,对于一个数,我们做质因数分解,分解过程中。记录合数出现的个数,同时质因数分解可以求得该数的因子个数,然后用因子个数减去合数因子个数就是()合因子数,其实就是对题目进行了一个翻译,用埃氏筛的方法很轻送就过了。

这里贴上题解的解释,可是十分简短了

埃式筛筛出质数,然后对于合数再筛一遍,然后统计每个数字被筛到的次数。桶排序一下即可。

/*************************************************
* @Author: maple
* @Date:   2020-02-08 13:10:59
* @Last Modified by:   maple
* @Last Modified time: 2020-02-08 13:32:07
* @Mark	
*************************************************/
#include <bits/stdc++.h>
#define CSE(x,y) memset(x,y,sizeof(x))
#define lowbit(x) x&(-x)
#define FAST ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x3f3f3f3f
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const int maxn=111111;

int proce(int x){
	int all=1,pr=1;
	for(int i=2;i*i<=x;i++){
		int mid=1;
		if(x%i==0)
			pr++;
		while(x%i==0){
			x/=i;
			mid++;
		}
		all*=mid;
	}
	if(x>1){
		pr++;
		all=all*2;
	}
	return all-pr;
}

int box[maxn];

int main()
{
	FAST;
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	#endif
	int n,m;
	cin>>n>>m;
	CSE(box,0);
	for(int i=1;i<=n;i++){
		//cout<<i<<":"<<proce(i)<<endl;
		box[proce(i)]++;
	}
	while(m--){
		int k;
		cin>>k;
		cout<<box[k]<<endl;
	}
	return 0;
}

I:牛牛的汉诺塔

额,对于这个题,我也是呵呵我自己了,这个题我是去研究了答案的规律然后总结出了通相公式,直接算出来的,虽然解释起来很简单,但是找通相公式的过程可谓是相当的凄惨。。。。。

题解讲了两种方法,记忆化搜索和递推(借助矩阵快速幂),这里贴上代码。

通相公式:

/*************************************************
* @Author: maple
* @Date:   2020-02-08 15:15:42
* @Last Modified by:   maple
* @Last Modified time: 2020-02-08 15:49:46
* @Mark	
*************************************************/
#include <bits/stdc++.h>
#define CSE(x,y) memset(x,y,sizeof(x))
#define lowbit(x) x&(-x)
#define Abs(x) x>=0?x:(-x)
#define FAST ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x3f3f3f3f
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const int maxn=11111;

ll arr[10],n;

ll qpow(ll a,ll b){
	ll base=1;
	while(b){
		if(b&1){
			base*=a;
		}
		a*=a;
		b>>=1;
	}
	return base;
}


int main()
{
	FAST;
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	#endif
	cin>>n;
	arr[1]=(qpow(2,2*(n/2-1)+3)+3*(n/2-1)+1)/9;
	arr[2]=(qpow(2,2*((n-1)/2-1)+3)+3*((n-1)/2-1)+1)/9*2+1;
	arr[3]=(qpow(4,(n-1)/2+1)-3*((n-1)/2)-4)/9;
	arr[4]=arr[1];
	arr[6]=arr[3];
	arr[5]=((qpow(4,(n-2)/2+1)-3*((n-2)/2)-4)/9)*2;
	cout<<"A->B:"<<arr[1]<<endl;
	cout<<"A->C:"<<arr[2]<<endl;
	cout<<"B->A:"<<arr[3]<<endl;
	cout<<"B->C:"<<arr[4]<<endl;
	cout<<"C->A:"<<arr[5]<<endl;
	cout<<"C->B:"<<arr[6]<<endl;
	cout<<"SUM:"<<arr[1]+arr[2]+arr[3]+arr[4]+arr[5]+arr[6]<<endl;
	return 0;
}

比赛场上想到这种解法可以说是相当亏了

题解

#include<bits/stdc++.h>
using namespace std;
struct node
{
 long long data[6];
 node()
 {
     memset(data,0,sizeof(data));
 }
 //A->B      0
 //A->C      1
 //B->A      2
 //B->C      3
 //C->A      4
 //C->B      5
};
node operator + (const node &A,const node &B)
{
 node C;
 for(int i=0;i<6;++i)
 {
     C.data[i]=A.data[i]+B.data[i];
 }
 return C;
}
void moveto(int x,int y,node &temp)
{
 if(x==0&&y==1)++temp.data[0];
 if(x==0&&y==2)++temp.data[1];
 if(x==1&&y==0)++temp.data[2];
 if(x==1&&y==2)++temp.data[3];
 if(x==2&&y==0)++temp.data[4];
 if(x==2&&y==1)++temp.data[5];
 return;
}
node dp[3][3][3][105];
bool vis[3][3][3][105];
node hanoi(int a,int b,int c,int n)
{
 if (vis[a][b][c][n])return dp[a][b][c][n];
 if (n==1)
 {
     moveto(a,c,dp[a][b][c][n]);
     vis[a][b][c][n]=true;
     return dp[a][b][c][n];
 }
 node temp;
 temp=temp+hanoi(a,c,b,n-1);
 moveto(a,c,temp);
 temp=temp+hanoi(b,a,c,n-1);
 vis[a][b][c][n]=true;
 return dp[a][b][c][n]=temp;
}
int n;
int main()
{
 scanf("%d",&n);
 node ans=hanoi(0,1,2,n);
 printf("A->B:%lld\n",ans.data[0]);
 printf("A->C:%lld\n",ans.data[1]);
 printf("B->A:%lld\n",ans.data[2]);
 printf("B->C:%lld\n",ans.data[3]);
 printf("C->A:%lld\n",ans.data[4]);
 printf("C->B:%lld\n",ans.data[5]);
 printf("SUM:%lld\n",(1LL<<n)-1);
}
#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <iomanip>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f;     ///1 061 109 567
const int negative_infinite = 0xcfcfcfcf;   ///-808 464 433
const double pi = acos(-1);
const int mod = 1e9 + 7;
const double eps = 1e-8;
const int MAXN = 1e5 + 117;
const int MAXM = 2e5 + 117;

int n;
LL dp[7][77][7];
/*
A B 0
A C 1
B A 2
B C 3
C A 4
C B 5
*/
int main() {
 scanf("%d", &n);
 memset(dp, 0, sizeof(dp));
 for(int i = 0; i < 6; i++) dp[i][1][i] = 1;
 for(int i = 2; i <= n; i++) {
     for(int j = 0; j < 6; j++) dp[j][i][j]++;

     for(int j = 0; j < 6; j++) dp[0][i][j] += dp[1][i - 1][j] + dp[5][i - 1][j];
     for(int j = 0; j < 6; j++) dp[1][i][j] += dp[0][i - 1][j] + dp[3][i - 1][j];
     for(int j = 0; j < 6; j++) dp[2][i][j] += dp[3][i - 1][j] + dp[4][i - 1][j];
     for(int j = 0; j < 6; j++) dp[3][i][j] += dp[2][i - 1][j] + dp[1][i - 1][j];
     for(int j = 0; j < 6; j++) dp[4][i][j] += dp[5][i - 1][j] + dp[2][i - 1][j];
     for(int j = 0; j < 6; j++) dp[5][i][j] += dp[4][i - 1][j] + dp[0][i - 1][j];
 }
 printf("A->B:%lld\n", dp[1][n][0]);
 printf("A->C:%lld\n", dp[1][n][1]);
 printf("B->A:%lld\n", dp[1][n][2]);
 printf("B->C:%lld\n", dp[1][n][3]);
 printf("C->A:%lld\n", dp[1][n][4]);
 printf("C->B:%lld\n", dp[1][n][5]);
 printf("SUM:%lld\n", ((LL)1 << n) - 1);
 return 0;
}

J:牛牛的宝可梦Go


posted @ 2020-02-26 22:27  落水清心  阅读(168)  评论(0编辑  收藏  举报