牛客寒假基础训练营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
",i,father[i],lchild[i],rchild[i]);
}
return 0;
}
E:牛牛的随机数
F:牛牛的Link Power I
这题我们可以去考虑前缀的方法去考虑这个问题,我们计算出每一个值它前面和它组成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;
}
G:牛牛的link power II
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 ",ans.data[0]); printf("A->C:%lld ",ans.data[1]); printf("B->A:%lld ",ans.data[2]); printf("B->C:%lld ",ans.data[3]); printf("C->A:%lld ",ans.data[4]); printf("C->B:%lld ",ans.data[5]); printf("SUM:%lld ",(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 ", dp[1][n][0]); printf("A->C:%lld ", dp[1][n][1]); printf("B->A:%lld ", dp[1][n][2]); printf("B->C:%lld ", dp[1][n][3]); printf("C->A:%lld ", dp[1][n][4]); printf("C->B:%lld ", dp[1][n][5]); printf("SUM:%lld ", ((LL)1 << n) - 1); return 0; }