20211202模拟赛总结

第一次写博客有点社死。

三道题都不难,但因为是第一次还是从头懵到了尾。不过还是很长知识。

比如我惊奇地发现一个评测点原来只有一组数据。。。

再比如我又惊奇地发现爆int是非常容易的一件事,引用m同学的精辟评论

“十年信竞一场空,没开longlong见祖宗”(它这么朗朗上口一定是想让我记住它

又比如因为freopen我干按了半天F11他都不出输入框。。。

还有些小小的庆幸比如我记住了文件名要复制

又比如我清楚地知道自己的数学水平而机智地没怎么写第一题。(其实下次可以直接蒙几个固定输出

不扯了上题。

1.计算系数

题目描述: 给定一个多项式(ax + by) k,请求出多项式展开后x n y m项的系数。

输入格式: 共一行,包含 5 个整数,分别为a,b,k,n,m,每两个整数之间用一个空格隔开。

输出格式: 输出共 1 行,包含一个整数,表示所求的系数,这个系数可能很大,输出对10007 取 模后的结果。

样例输入: 1 1 3 1 2 //这个样例太过于水千万不要相信它

样例输出: 3

数据范围

对于 30%的数据,有0≤k≤10;

对于 50%的数据,有a = 1,b = 1;

对于 100%的数据,有0≤k≤1,000,0≤n, m≤k,且n + m = k,0≤a,b≤1,000,000//敲黑板

首先可以令a=b=1,用不屈的意志算出k=1,2,3,4时的系数情况,这样我们就会得到一个大大的杨辉三角形。

用数组模拟:

s[1][1]=1;//数组预先赋初值0
for(int i=2;i<=k+1;i++){//i初值为2
  for(int j=1;j<=i;j++){
    s[i][j]=s[i-1][j]+s[i-1][j-1];//由于这里的i-1和j-1所以前面从s[1][1]开始
  s[i][j]%=10007;
  }
}

最后加入a和b,容易发现要将结果乘n个a,m个b。

long long int ans=s[k+1][m+1];
for(int i=0;i<n;i++) ans=(ans%10007*a%10007)%10007;
for(int i=0;i<m;i++) ans=(ans%10007*b%10007)%10007;

敲黑板!!!

不是连续不断地对10007取模就可以高枕无忧,看了前面的数据范围我们会发现括号内表达式很有可能没来得及取模就爆int,所以这时我们要请出亲爱的longlong。

全部代码:

#include<bits/stdc++.h>
using namespace std;
int s[1001][1001];
int main(){
  //freopen("factor.in","r",stdin);
  //freopen("factor.out","w",stdout);
  int a,b,k,m,n;
  scanf("%d %d %d %d %d",&a,&b,&k,&n,&m);
  s[1][1]=1;
  for(int i=2;i<=k+1;i++){
    for(int j=1;j<=i;j++){
      s[i][j]=s[i-1][j]+s[i-1][j-1];
      s[i][j]%=10007;
    }
  }
  long long int ans=s[k+1][m+1];
  for(int i=0;i<n;i++) ans=(ans%10007*a%10007)%10007;
  for(int i=0;i<m;i++) ans=(ans%10007*b%10007)%10007;
  printf("%lld",ans);
  return 0;
}

 2.汉诺塔问题

题目描述: 汉诺塔由编号为 1 到 n 大小不同的圆盘和三根柱子 a,b,c 组成。开始时,这 n 个圆盘由大到小依次套在 a 柱 上,如图所示。要求把 a 柱上 n 个圆盘按下述规则移到 c 柱上:

(1)一次只能移一个圆盘,它必须位于某个柱子的顶部;

(2)圆盘只能在三个柱上存放;

(3)任何时刻不允许大盘压小盘。

将这 n 个盘子从 a 柱移动到到 c 柱上,最少需要移动多少次? 

输入格式: 第一行输入一个正整数 n(1<=n<=30),表示圆盘的数量。

输出格式: 输出一个数表示最少需要移动的次数。

样例输入: 3

样例输出: 7

 

当时的我非常开心:哇这不openjudge2.2刚做完嘛!有这个想法多半下场一个比一个惨。

典中典不必多讲。

这道题与题库上不一样的就是不需要输出每次如何移动,去掉后发现其中有大量的重复计算(我当时怎么就没发现

#include<bits/stdc++.h>
using namespace std;
int cnt,a[100];
int movee(int n){
  if(a[n]!=0) return a[n];
  if(n==1) cnt++;
  else{
    a[n-1]=movee(n-1);
    cnt+=(a[n-1]+1);
  }
  return cnt;
}
int main(){
  //freopen("hanoi.in","r",stdin);
  //freopen("hanoi.out","w",stdout);
  int n;
  cin>>n;
  cout<<movee(n);
  return 0;
}

 

 总而言之这种题几乎都需要数组a来存储算过的结果,毕竟我们都爱AC而不爱TLE。

当然我们身为祖国的花朵不能忘了输入30检验,发现刚好没爆int。

3.骨牌覆盖

作为递归里为数不多我会的题,我又非常开心。

题目描述: 有 2 行 n 列的长方形方格,要求用 n 个 1*2 的骨牌铺满。有多少种铺法? 如 n=3 时有以下 3 种覆盖方法:

                 

 

输入格式: 第一行输入一个正整数 n(1<=n<=50)

输出格式: 输出一个整数表示方案数。

样例输入:3 //没什么用的样例又增加了

样例输出:3

 递归终止很简单,显然n<=3时只有n种放法(样例是3当然不能辜负它

n更大的时候每次两种放法:一个竖着的骨牌或者两个横着的骨牌。

long long int a[1000];
long long int f(int n){
  if(a[n]!=0) return a[n];
  if(n<=3) return a[n]=n;
  return a[n]=f(n-1)+f(n-2);
}

这么可爱的递归当然要用一个数组存储它。

于是整个程序简单了起来。

#include<bits/stdc++.h>
using namespace std;
long long int a[1000];
long long int f(int n){
  if(a[n]!=0) return a[n];
  if(n<=3) return a[n]=n;
  return a[n]=f(n-1)+f(n-2);
}
int main(){
  //freopen("domino.in","r",stdin);
  //freopen("domino.out","w",stdout);
  int n;
  cin>>n;
  cout<<f(n);
  return 0;
}

身为祖国的花朵我们当然不能忘记输入50看一眼并请出亲爱的longlong。

最后首尾呼应一下。

“十年信竞不想空,当开longlong敲警钟”

 

posted @   专吃小仙女  阅读(72)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示