比赛链接

官方题解

A-积木大赛

题目描述 link

题解

标签:模板题,一点点思维+二维差分+二维前缀和

借这道题机会复习了一下二维差分+二维前缀和这两个东西。

首先题目让我们求总的表面积,实际上可以拆分成两部分:上下表面积+前后左右表面积

1.上下表面积的话,根据俯视图想一想,就是有被积木覆盖额面积\(*2\);

2.前后左右表面积的话,感性理解一下,只要他的高度大于他的前/后/左/右的积木高度,那么它这一块就可以露出来,所以就是与前后左右积木高度的差值。

这两个问题都要用到在某一坐标积木的高度。那只要二维差分一下,最后统计一下二维前缀和,就可求得那个位置上积木的高度了。二维差分可以自己根据求二维前缀和的过程推一下。

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. bool nc1;
  4. const int N=5010;
  5. int p[N][N],n,m,q;
  6. const int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
  7. inline bool ok(int x,int y){
  8. if(x<1||y<1||x>n||y>m)return 0;
  9. return 1;
  10. }
  11. bool nc2;
  12. int main(){
  13. //cout<<(&nc2-&nc1)/1024<<endl;
  14. scanf("%d%d%d",&n,&m,&q);
  15. while(q--){
  16. int a,b,c,d;
  17. scanf("%d%d%d%d",&a,&b,&c,&d);
  18. p[a][b]++;
  19. p[a][d+1]--;
  20. p[c+1][b]--;
  21. p[c+1][d+1]++;
  22. }
  23. for(register int i=1;i<=n;i++)
  24. for(register int j=1;j<=m;j++)p[i][j]=p[i-1][j]+p[i][j-1]+p[i][j]-p[i-1][j-1];
  25. long long up=0,ans=0;
  26. for(register int i=1;i<=n;i++)for(register int j=1;j<=m;j++){
  27. if(!p[i][j])continue;
  28. up++;
  29. int tmp=ans;
  30. for(register int k=0;k<=3;k++){
  31. int x=dx[k]+i,y=dy[k]+j;
  32. if(!ok(x,y))ans+=p[i][j];
  33. else if(p[i][j]>p[x][y])ans+=p[i][j]-p[x][y];
  34. }
  35. }
  36. printf("%lld\n",2*up+ans);
  37. }

B-破碎的序列

题目描述 link

题解

标签:化简问题+计数Dp

先看看题面当她开心时(m=1)她喜欢不存在长度为奇数且大于1的回文子串的数列,当她不开心时(m=0)她喜欢不存在长度为偶数且大于1的回文子串的数列 。仔细想想根本不用搞什么回文串,化简题意后就是:

当m=1时:\(a[i]!=a[i+2]\)

当m=0时:\(a[i]!=a[i+1]\)

看数据范围\(n,k<=2e5\),很明显是个计数Dp(当然也可以不用Dp,直接用数学方法计算,但Dp比较直观暴力)。定义状态\(dp[i][0/1]\)表示现在合法地填完了数列的前\(i\)项,且第\(i\)项与\(nxt[i]\)是否相同(0/1)时的方案数。

完整代码如下,可以在理解cas1的前提下再去看cas2,总时间复杂度为\(O(N)\)。

  1. #include<bits/stdc++.h>
  2. #define mod 998244353
  3. using namespace std;
  4. const int N=2e5+10;
  5. int n,m,k,a[N],nxt[N];
  6. int dp[N][2];
  7. void cas1(){//a[i]!=a[i+1]
  8. for(int i=n;i>=1;i--){
  9. if(!a[i+1])nxt[i]=nxt[i+1];
  10. else nxt[i]=a[i+1];
  11. }
  12. if(a[1]&&a[1]==nxt[1])dp[1][1]=1;
  13. else if(a[1])dp[1][0]=1;
  14. else{dp[1][1]=1;dp[1][0]=k-1;}
  15. for(int i=2;i<=n;i++){
  16. if(a[i]&&a[i]==nxt[i])dp[i][1]=dp[i-1][0];
  17. else if(a[i])dp[i][0]=dp[i-1][0];
  18. else{
  19. dp[i][1]=dp[i-1][0];
  20. dp[i][0]=1ll*dp[i-1][0]*(k-2)%mod;
  21. dp[i][0]+=1ll*dp[i-1][1]*(k-1)%mod;
  22. dp[i][0]%=mod;
  23. }
  24. }
  25. printf("%d\n",(dp[n][0]+dp[n][1])%mod);
  26. }
  27. void cas2(){//a[i]!=a[i+2]
  28. for(int i=n-2;i>=1;i--){
  29. if(!a[i+2])nxt[i]=nxt[i+2];
  30. else nxt[i]=a[i+2];
  31. }
  32. for(int i=1;i<=2;i++){
  33. if(a[i]&&a[i]==nxt[i])dp[i][1]=1;
  34. else if(a[i])dp[i][0]=1;
  35. else{dp[i][1]=1;dp[i][0]=k-1;}
  36. }
  37. for(int i=3;i<=n;i++){
  38. if(a[i]&&a[i]==nxt[i])dp[i][1]=dp[i-2][0];
  39. else if(a[i])dp[i][0]=dp[i-2][0];
  40. else{
  41. dp[i][1]=dp[i-2][0];
  42. dp[i][0]=1ll*dp[i-2][0]*(k-2)%mod;
  43. dp[i][0]+=1ll*dp[i-2][1]*(k-1)%mod;
  44. dp[i][0]%=mod;
  45. }
  46. }
  47. int res1=(dp[n-1][0]+dp[n-1][1])%mod,res2=(dp[n][0]+dp[n][1])%mod;
  48. printf("%d\n",1ll*res1*res2%mod);
  49. }
  50. int main(){
  51. scanf("%d%d%d",&n,&k,&m);
  52. for(int i=1;i<=n;i++)scanf("%d",&a[i]);
  53. if(m==0)cas1();
  54. else cas2();
  55. return 0;
  56. }

C-分班问题

题目描述 link

题解

标签:组合数+数学推导化简+Lucas定理

这道题官方题解写的非常详细,这里完整过程就不赘述了。讲一下主要的解题过程

一、40%数据(\(n,m,T<=2000\))的暴力做法根据题意很好推出:

  1. for(int i=1;i<=min(n,m);i++)ans+=C(n,i)*C(m,i)*2*i;

组合数可以在\(O(N^2)\)时间内预处理出,每个询问可以在\(O(N)\)的时间内完成。

二、60%数据(\(T<=1e5,n,m<=1e6\))做法可以根据通过数学化简上面那个\(O(N)\)循环:

  1. ans=2*m*C(n+m-1,n-1)

先在\(O(N)\)时间内预处理出\(1e6\)范围内的模逆元和阶乘,然后询问就可以在\(O(1)\)时间内解决了。但现在的瓶颈在于\(O(N)\)预处理,所以下面考虑使用Lucas定理

三、100%数据(\(T<=1e5,n,m<=1e18\))

发现\(n,m\)过大按常规方法无法求得组合数,并且题目给定的模数为质数,所以可以使用\(Lucas定理\)解决,关于Lucas定理

  1. #include<bits/stdc++.h>
  2. #define mod 19260817
  3. using namespace std;
  4. typedef long long ll;
  5. const int N=mod+10;
  6. int mny[N],fac[N];
  7. inline ll read(){
  8. ll x=0;char c=getchar();
  9. while(c<'0'||c>'9')c=getchar();
  10. while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
  11. return x;
  12. }
  13. int ksm(int x,int d){
  14. int res=1;
  15. while(d){
  16. if(d&1)res=1ll*res*x%mod;
  17. x=1ll*x*x%mod;d>>=1;
  18. }
  19. return res;
  20. }
  21. void init(){//预处理阶乘fac,模逆元mny
  22. fac[0]=1;
  23. for(int i=1;i<mod;i++)fac[i]=1ll*fac[i-1]*i%mod;
  24. mny[mod-1]=ksm(fac[mod-1],mod-2);
  25. for(int i=mod-2;i>=0;i--)mny[i]=1ll*mny[i+1]*(i+1)%mod;
  26. }
  27. int C(ll a,ll b){//Lucas
  28. if(a<b)return 0;
  29. if(a>=mod)return 1ll*C(a%mod,b%mod)*C(a/mod,b/mod)%mod;
  30. return (1ll*fac[a]*mny[a-b]%mod)*mny[b]%mod;
  31. }
  32. int main(){
  33. init();
  34. int T=read();
  35. while(T--){
  36. ll n=read(),m=read();
  37. printf("%d\n",1ll*2*m%mod*C(n+m-1,n-1)%mod);
  38. }
  39. }

最后bb一句:这是牛客最后一场了,第2,4,5场由于题目质量不佳没时间写就空着了qwq

牛客NOIP暑期七天营-提高组6的更多相关文章

  1. 牛客NOIP暑期七天营-提高组1

    牛客NOIP暑期七天营-提高组1 链接 A 边权可为0就排序建一条链子. 但是边权不为0 除了第一个有0的不行. x连向上一个比他小的数. 期间判断有无解. #include <bits/std ...

  2. 牛客NOIP暑期七天营-提高组5+普及组5

    ————提高组———— 第一题:deco的abs 题目链接:https://ac.nowcoder.com/acm/contest/934/A 因为每个数都可以加任意次 d ,所以可以推出 0 < ...

  3. 牛客NOIP暑期七天营-提高组3

    第一题:破碎的矩阵 题目链接:https://ac.nowcoder.com/acm/contest/932/A    刚看到这题的时候感觉特别熟悉...诶,这不就是codeforces某场比赛的某某 ...

  4. 牛客NOIP暑期七天营-提高组2

    第一题:ACGT 题目链接:https://ac.nowcoder.com/acm/contest/931/A trie树.hash.map遍历  ①.trie树上的节点多记一个rest值表示还有多少 ...

  5. 牛客NOIP暑期七天营-提高组6C:分班问题 (组合数)

    题意:A班有N个人,B班有M个人,现在要组成一个新的班级C班,为了公平,从AB班各抽相同人数的人. 现在求所有方案中,人数之和是多少. 思路:即求Σ k*C(N,k)*C(M,k);    先忽略这个 ...

  6. 牛客NOIP暑期七天营-提高组5

    A:deco的abs. 水题,先%,然后相邻两个数min()一下差值. #include<bits/stdc++.h> #define ll long long using namespa ...

  7. 牛客NOIP暑期七天营-提高组2C:滑块(平衡树) (这里rope骗分)

    A:hash 或者 map 或者trie. #include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) usin ...

  8. 牛客NOIP暑期七天营-提高组1 解题报告

    https://ac.nowcoder.com/acm/contest/920#question A 构造+双指针 发现m的限制是1e5,而点数是5e4,所以不能构造太多的边,思考一下最短路树的定义. ...

  9. 牛客NOIP暑期七天营-普及组2D

    链接:https://ac.nowcoder.com/acm/contest/926/D来源:牛客网 在一维坐标系中,给定 n条有颜色的线段,第 i条线段的左右端点分别为 li​和 ri​,此外它的颜 ...

随机推荐

  1. 数据库MySQL--基础查询

    1.查询字段 查询表某字段:select 字段名 from 表名: 查询表内所有字段:select * from 表名: (当字段和关键字重名是用( ` )着重号区分 ) 2.查询常量值 select ...

  2. 【JZOJ6370】基础 fake 练习题

    description 装饰者坐在树荫下听着长者讲述以前的故事: 大神 yk 非常喜欢树,便钦点班里的 n 个小蒟蒻站在一棵 n 个点以 1 为根的树上,并且每个点上恰好有 1 个小蒟蒻. 大神 yk ...

  3. GCRoots 对象

    GC Roots 虚拟机栈(栈帧中的本地变量表)中引用的对象 方法区中的类静态属性引用的对象 方法区中的常量引用的对象 原生方法栈(Native Method Stack)中 JNI 中引用的对象 可 ...

  4. thinkphp 系统流程

    用户URL请求 调用应用入口文件(通常是网站的index.php) 载入框架入口文件(ThinkPHP.php) 记录初始运行时间和内存开销 系统常量判断及定义 载入框架引导类(Think\Think ...

  5. VS2010-MFC(常用控件:滚动条控件Scroll Bar)

    转自:http://www.jizhuomi.com/software/191.html 滚动条控件简介 滚动条大家也很熟悉了,Windows窗口中很多都有滚动条.前面讲的列表框和组合框设置了相应属性 ...

  6. R软件导入数据_r语言怎么导入数据_R软件导入数据

    R软件导入数据_r语言怎么导入数据_R软件导入数据 R软件导入数据 1.Rcmdr安装包导入数据: 1.安装Rcmdr包,输入: install.packages("Rcmdr") ...

  7. 控制变量行业年份回归时在STATA里怎么操作_stata 分年份回归

    控制变量行业年份回归时在STATA里怎么操作_stata 分年份回归 我希望做一个多元回归,但需要控制年份和行业. (1)年份有7年2006-2012,听说STATA可以自动设置虚拟变量,请问命令是怎 ...

  8. 标记excel中输入的重复数据

    首先选中需要标记重复的数据列 开始 -> 条件格式 -> 突出显示单元格规则 -> 重复值 选择相应的颜色即可 效果如下:

  9. php 取某一日期的前一天

    代码为: $date = “2009-01-01”;$time = strtotime($date) – 3600*24;echo date(‘Y-m-d’,$time); 或者一句:echo dat ...

  10. virtualbox导入winXP系统OVA文件重启

    1,开启虚拟机 2,按f8进入安全模式,然后修改注册表: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Processor HKEY_LOC ...