• CSP-S模拟测试69 题解


    一如既往的垃圾,又回到了那个场场垫底的自己,明明考场上都想到正解了,但是就是拿不到分,可能是互奶把rp用光了吧以后一定加强训练代码能力。

    T1:

    考场上一直yy矩阵快速幂,虽然自己矩阵快速幂一点都不会还是硬着头皮yy,发现不可做之后并没有及时转化思路,但其实自己预处理的数组就是正解。

    切记:不仅矩阵快速幂是log的,普通快速幂也是2333

    然后这题其实很水啊,我们设$dp[i][j]$为前$i$列放$j$个棋子的方案数,然后枚举最后一列放多少个棋子就好了。

    转移方程为$dp[i][j]=sum{dp[i-1][j-k]*C_n^k}$,这样转移m列显然不行,考虑性质,第$i$列和第$i+kn$列的摆放方式一定相同,所以后面的组合数乘还有多少这样的列就好了即${C_n^k}^{frac{m-i}{n}+1}$,但这样的复杂度是$O(n^4logn)$的,发现组合数可以预处理,于是去掉了log

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e5+10,mod=1e9+7;
     4 #define int long long
     5 int n,m,c,fac[N],inv[N];
     6 int f[105][105*105],pre[105][105*105];
     7 int min(int a,int b){
     8     return a<b?a:b;
     9 }
    10 int qpow(int a,int b){
    11     int ans=1;
    12     while(b){
    13         if(b&1) ans=ans*a%mod;
    14         b>>=1;
    15         a=a*a%mod;
    16     }
    17     return ans%mod;
    18 }
    19 int C(int a,int b){
    20     return fac[a]*inv[b]%mod*inv[a-b]%mod;
    21 }
    22 signed main(){
    23     fac[0]=1;
    24     for(int i=1;i<=10001;++i) fac[i]=fac[i-1]*i%mod;
    25     inv[10001]=qpow(fac[10001],mod-2);
    26     for(int i=10001;i;--i) inv[i-1]=inv[i]*i%mod;
    27     scanf("%lld%lld%lld",&n,&m,&c);
    28     f[0][0]=1;
    29     for(int i=0;i<=n;++i) for(int j=0;j<=max(n,c);++j) pre[i][j]=qpow(C(n,j),(m-i)/n+1)%mod;
    30 //    for(int i=1;i<=n;++i,cout<<endl) for(int j=1;j<=n;++j) cout<<pre[i][j];
    31     for(int i=1;i<=n;++i){
    32         for(int j=0;j<=c;++j){
    33             for(int k=0;k<=min(n,j);++k){
    34                 (f[i][j]+=f[i-1][j-k]*pre[i][k]%mod)%=mod;
    35 //                cout<<pre[i][k]<<" "<<qpow(C(n,k),(m-i)/n+1)<<endl;
    36             }
    37         }
    38     }
    39     printf("%lld",f[n][c]%mod);
    40 }
    41 /*
    42 2 3 1
    43 */
    chess

    T2:

    考场上先想到单调栈,但是后来成功理解错题意对拍5w组WA0 2333。

    如果理解对题意的话单调栈就挺明显了吧,肯定要找它前面第一各比他大的,那么答案一定在这段区间中,有一个比较明显的贪心就是,最优决策点一定是在,高度最小的那个点,稍想一下就可以明白。

    所以在弹栈的时候每次更新,高度最小的下标即可。

    对于输入量大的题,快读真的很有必要。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e7+10;
     4 pair<int,int > s[N];
     5 int a[N],sta[N],top;
     6 inline int min(int a,int b){return a<b?a:b;}
     7 inline int max(int a,int b){return a>b?a:b;} 
     8 inline int read(){
     9     register int p=0;register char ch=getchar();
    10     while(ch<'0'||ch>'9') ch=getchar();
    11     while(ch>='0'&&ch<='9') p=(p<<3)+(p<<1)+ch-48,ch=getchar();
    12     return p;
    13 }
    14 
    15 int main(){
    16     int n;
    17     scanf("%d",&n);++n;
    18     for(register int i=1;i^n;++i) a[i]=read();
    19 //    for(int i=1;i<=n;++i) s[i].first=a[i],s[i].second=i;
    20     sta[++top]=0;a[0]=0x7fffffff;
    21     register int ans=1;
    22     for(register int i=1;i^n;++i){
    23         s[i]=make_pair(a[i],i);
    24         while(a[i]>=a[sta[top]]){
    25             s[i]=min(s[i],s[sta[top--]]);
    26             
    27         }ans=max(ans,i-s[i].second+1);
    28         sta[++top]=i;
    29     }
    30     printf("%d",ans);
    31 }
    array

    T3:

    回滚莫队裸题。

    就维护两个数组now1,now2,分别代表x向左向右能伸展的最长连续值域。

    分别用x+1,x-1更新。还有就是更新一下这整段区间的左右端点以保证以后更新答案正确,中间的不用更新因为不会在插入了。

    当这个区间左端点和上一个区间左端点不一样时,直接清空你now1,now2数组。

    做完了之后觉的理解更加深入了。

    放个回滚莫队讲解链接

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e6+10;
     4 int blo[N];
     5 int sta1[N],sta2[N],top;
     6 struct node{
     7     int l,r,id,ld;
     8     bool friend operator < (node a,node b){
     9         return blo[a.l]==blo[b.l]?(a.r<b.r):blo[a.l]<blo[b.l];
    10     }
    11 }ask[N];
    12 int now1[N],now2[N],a[N],ans[N];
    13 int main(){
    14 //freopen("ants1.in","r",stdin);
    15 //freopen("my.out","w",stdout);
    16     int n,m;
    17     scanf("%d%d",&n,&m);
    18     int size=sqrt(n);
    19     for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    20     for(int i=1;i<=m;++i){
    21         scanf("%d%d",&ask[i].l,&ask[i].r);
    22         ask[i].id=i;
    23         ask[i].ld=(ask[i].l-1)/size+1;
    24     }
    25     for(int i=1;i<=n/size+1;++i){
    26         for(int j=size*(i-1)+1;j<=size*i;++j) blo[j]=i;
    27     }
    28     sort(ask+1,ask+m+1);
    29     int r=0,l=1,res=0;
    30     for(int i=1;i<=m;++i){
    31         if(ask[i].ld!=ask[i-1].ld){
    32             for(int j=0;j<=n;++j) now1[j]=now2[j]=0;
    33             res=0;
    34             l=r=ask[i].ld*size;
    35         }
    36         while(ask[i].r>r){
    37             ++r;
    38             int x=a[r];
    39             now1[x]=now1[x+1]+1;
    40             now2[x]=now2[x-1]+1;
    41             int kh=now1[x]+now2[x]-1;
    42             now1[x-now2[x]+1]=kh;
    43             now2[x+now1[x]-1]=kh;
    44             res=max(kh,res);
    45         }
    46         top=0;
    47         int tmp=res;
    48         for(int j=ask[i].l;j<=min(ask[i].r,l);++j){
    49             int x=a[j];
    50             now1[x]=now1[x+1]+1;
    51             now2[x]=now2[x-1]+1;
    52             int kh=now1[x]+now2[x]-1;
    53             sta1[++top]=x-now2[x]+1;
    54             sta2[top]=now1[x-now2[x]+1];
    55             sta1[++top]=x+now1[x]-1;
    56             sta2[top]=now2[x+now1[x]-1];
    57             now1[x-now2[x]+1]=kh;
    58             now2[x+now1[x]-1]=kh;
    59             tmp=max(kh,tmp);
    60         }
    61         for(int j=top;j;--j){
    62             if(j&1) now1[sta1[j]]=sta2[j];
    63             else now2[sta1[j]]=sta2[j];
    64         }
    65         for(int j=ask[i].l;j<=min(l,ask[i].r);++j){
    66             now1[a[j]]=0;
    67             now2[a[j]]=0;
    68         }
    69         ans[ask[i].id]=tmp;
    70     }
    71     for(int i=1;i<=m;++i) printf("%d
    ",ans[i]);
    72 }
    ants
  • 相关阅读:
    C#学习笔记_01_基础内容
    C#学习笔记_03_运算符
    C#学习笔记_02_数据类型
    统计学习方法(一)
    《史蒂夫·乔布斯传》读书笔记
    《孵化twitter》读书笔记
    保存和恢复 Android Fragment 的状态
    计算机视觉中的边缘检测
    Android开发的过去、现在和将来
    Python常用的第三方库
  • 原文地址:https://www.cnblogs.com/leom10/p/11660786.html
Copyright © 2020-2023  润新知