A 牛牛的DRB迷宫I
思路:暴力dfs,时间复杂度O(2^n)超时,改dp。
定义状态:dp[i][j]表示起点(1,1)到坐标(i,j)的路径条数。
边界:因为只能向右或者向下走,所以dp[1][i]和dp[i][1]都可以计算出来,dp[1][1]=1。
状态转移方程:dp[i][j]=dp[i][j-1]+dp[i-1][j]; (不带约束,具体看代码)
代码:
#include<iostream>
using namespace std;
const int mod = 1e9 +7;
int n,m;
char maze[100][100];
int dp[100][100]={0};
/* dp[i][j]:从起点(1,1)到(i,j)的路径条数 */
int main(){
cin>>n>>m;
dp[1][1]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf(" %c",&maze[i][j]);
}
}
for(int i=2;i<=n;i++){
if(maze[i-1][1]=='B'||maze[i-1][1]=='D')dp[i][1]=dp[i-1][1];
}
for(int i=2;i<=m;i++){
if(maze[1][i-1]=='B'||maze[1][i-1]=='R')dp[1][i]=dp[1][i-1];
}
for(int i=2;i<=n;i++){
for(int j=2;j<=m;j++){
if(maze[i][j-1]=='B'||maze[i][j-1]=='R')
dp[i][j]=(dp[i][j]+dp[i][j-1])%mod;
if(maze[i-1][j]=='B'||maze[i-1][j]=='D')
dp[i][j]=(dp[i][j]+dp[i-1][j])%mod;
dp[i][j]=dp[i][j-1]+dp[i-1][j];
}
}
cout<<dp[n][m]%mod;
}
C 牛牛的数组越位
思路:题目虽然很长,但是仔细研究一下发现并不难,简单模拟一下即可。
代码:
#include<iostream>
#include<cstring>
using namespace std;
typedef long long int ll;
const int maxn = 1e3 + 10;
ll a[maxn][maxn];
int main(){
int t;cin>>t;
while(t--){
int n,m,p;cin>>n>>m>>p;
memset(a,0,sizeof(a));
bool ub=false,re=false;
while(p--){
int x,y,v;cin>>x>>y>>v;
if(x<0||y<0||x>=n||y>=m)ub=true;
int k=m*x+y;
int fx=k/m;
int fy=k%m;
if(fx<0||fy<0||fx>=n||fy>=m)re=true;
else a[fx][fy]=v;
}
if(re&&ub)cout<<"Runtime error"<<endl;
else{
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
if(ub)cout<<"Undefined Behaviour"<<endl;
else cout<<"Accepted"<<endl;
}
}
}
D 牛牛与二叉树的数组存储
思路:题目也很长但是也不难,模拟一下就行了。
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;
int n;
struct node{
int data,pos;
}a[maxn],b[maxn];
bool cmp(node a,node b){
return a.data<b.data;
}
int main(){
cin>>n;
int count=0,root=0;
memset(a,-1,sizeof(a));
memset(b,-1,sizeof(b));
for(int i=1;i<=n;i++){
cin>>a[i].data;
a[i].pos=i;
b[i].data=a[i].data;b[i].pos=a[i].pos;
if(i==1)root=a[i].data;
if(a[i].data!=-1)count++;
}
cout<<"The size of the tree is "<<count<<endl;
cout<<"Node "<<root<<" is the root node of the tree"<<endl;
sort(a+1,a+n+1,cmp);
int cnt=1;
for(int i=1;i<=n;i++){
if(a[i].data!=-1)
cout<<"The father of node "<<cnt++<<" is "<<b[a[i].pos/2].data<<", the left child is "<<b[a[i].pos*2].data<<", and the right child is "<<b[a[i].pos*2+1].data<<endl;
}
}
H 牛牛的k合因子数
思路:
先O(nlogn)筛法,求出prime[i]判断每个数是否是素数,然后枚举[1,n]求每个数因子直接用prime[i]判断该数是否是合数,时间复杂度O(n^2) --》 超时。
其实在求筛法的时候就可以求解答案,因为我们知道素数的因子为合数的个数是0(1本身,本身还是素数),合数的因子为合数的个数起码是1因为1本身是因子,而本身又是合数,在筛法的时候我们每找到一个合数让他的倍数因子个数++(这里指因子为合数),因为他的倍数一定可以由当前这个数组成,而当前这个数又是合数。。。。。具体看代码。
代码:
#include<iostream>
#include<cstring>
using namespace std;
typedef long long int ll;
int n,m;
const int maxn = 1e5+10;
bool prime[maxn];
int f[maxn],cnt[maxn];
/* cnt[i]:表示数字i的因子中为合数的数量 f[i]:[1,n]中各数字的因子为合数且数量为i的数量 */
void init(){
memset(prime,true,sizeof(prime));
for(int i=2;i<=n;i++){
if(prime[i]==true){
for(int j=i+i;j<=n;j+=i){
prime[j]=false;
}
}else{
for(int j=i;j<=n;j+=i)
cnt[j]++;
}
f[cnt[i]]++;//统计当前这个数的因子中为合数的数量
}
}
int main(){
cin>>n>>m;
init();
while(m--){
int k;cin>>k;
cout<<f[k]<<endl;
}
}
F 牛牛的Link Power I
思路:
cnt统计1的个数,sum统计前面所有的1同时移动到当前位置的距离,ans表示答案。
没找到一个1cnt++,然后sum每次移动cnt次,表示前面n个1同时向后面移动,每次又找到一个1更新答案,再把这个1加进来,继续扫描,时间复杂度O(n)。
代码:
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
char a[maxn];
int cnt,ans,sum;
const int mod = 1e9 + 7;
/* cnt:统计1的个数 sum:前面所有的1同时移动到当前位置的距离 */
int main(){
int n;cin>>n;
scanf("%s",a);
for(int i=0;i<n;i++){
sum=(sum+cnt)%mod;
if(a[i]=='1'){
cnt++;
ans=(ans+sum)%mod;
}
}
cout<<ans<<endl;
}
I 牛牛的汉诺塔
思路:
写一个正常的汉诺塔求出前面7项
通过找关系可以求出关系公式,然后代码就很好写了。
代码:
#include<iostream>
#include<math.h>
using namespace std;
long long int a,b,c,d,e,f;
int main(){
long long int n;cin>>n;
for(int i=1;i<=n;i++){
if(i&1){
b=a+d+1;
c=d+e;
f=a+e;
}else{
a=b+c;
d=b+c;
e=a;
}
}
cout<<"A->B:"<<a<<endl;
cout<<"A->C:"<<b<<endl;
cout<<"B->A:"<<c<<endl;
cout<<"B->C:"<<d<<endl;
cout<<"C->A:"<<e<<endl;
cout<<"C->B:"<<f<<endl;
cout<<"SUM:"<<((long long int)1<<n)-1<<endl;
}