2017-11-3离线赛总结

来源:互联网 发布:雨人医药软件 编辑:程序博客网 时间:2024/06/06 03:25

    • 题目
    • 失分小结
      • 估分
      • 实际分数
    • 题解
      • T1
        • P70
          • CODE
        • P100
          • CODE
      • T2
        • P90
          • CODE
        • P95
          • CODE
        • P100
          • CODE
      • T3
        • P100
          • CODE

题目

3802,3803,3804.

失分小结

估分

70+80+30=180 (小C说这是基础分)

实际分数

70+90+10=170
T2只要加上前缀和优化就AC了啊啊啊啊啊
当然T3不小心炸了

题解

T1

P70

杨辉三角

CODE
#include<cstdio>#define N 1005#define P 1000000007int a,b,n;bool check(int x) {    while(x) {        int t=x%10;        if(t!=a&&t!=b)return 0;        x/=10;    }    return 1;}int main() {    scanf("%d %d %d",&a,&b,&n);    int C[N][N];    C[0][0]=C[1][0]=C[1][1]=1;    for(int i=2; i<=n; i++) {        C[i][0]=C[i][i]=1;        for(int j=1; j<i; j++)            C[i][j]=(C[i-1][j]+C[i-1][j-1])%P;    }    int ans=0;    for(int i=0; i<=n; i++)        if(check(a*i+b*(n-i)))            ans=(ans+C[n][i])%P;    printf("%d",ans);    return 0;}

P100

正解乘法逆元:

CODE
#include<cstdio>#define P 1000000007using namespace std;int a,b,n;bool check(int x) {    while(x) {        int t=x%10;        if(t!=a&&t!=b)return 0;        x/=10;    }    return 1;}int fast(int x,int p) {    int res=1;    while(p) {        if(p&1)res=1ll*res*x%P;        x=1ll*x*x%P;        p>>=1;    }    return res;}int main() {    scanf("%d %d %d",&a,&b,&n);    int ans=0,c=1;    for(int i=0; i<=n; i++) {        if(check(i*a+(n-i)*b))ans=(ans+c)%P;        c=1ll*c*(n-i)%P*fast(i+1,P-2)%P;    }    printf("%d\n",ans);    return 0;}

T2

P90

O(n4).
定义dp[i][j]表示前i个数字切完最后一个长度为j(范围[ij+1,i]
我也不知道为什么O(n4)有90分…

CODE
#include<cstdio>#include<iostream>#define N 3005#define P 1000000007using namespace std;char a[N];int dp[N][N];int n;int ans=0;bool check(int st1,int st2) {    int ed1=st2-1;    for(; st1<=ed1; st1++,st2++) {        if(a[st1]>a[st2])return 0;        if(a[st2]>a[st1])return 1;    }    return 0;}int main() {    scanf("%d",&n);    scanf("%s",a+1);    for(int i=1; i<=n; i++) {        for(int j=1; j<i; j++) {            if(a[i-j+1]!='0') {                for(int k=1; k<j; k++) {                    dp[i][j]=(dp[i][j]+dp[i-j][k])%P;                }                if(check(i-j-j+1,i-j+1))                    dp[i][j]=(dp[i][j]+dp[i-j][j])%P;            }        }        dp[i][i]=1;    }    int ans=0;    for(int i=1; i<=n; i++)ans=(ans+dp[n][i])%P;    printf("%d",ans);    return 0;}

P95

O(n3).
网站上95本地100.
前缀和优化…

CODE
#include<cstdio>#include<iostream>#define N 3005#define P 1000000007using namespace std;char a[N];int dp[N][N];int n;int ans=0;bool check(int st1,int st2) {    int ed1=st2-1;    for(; st1<=ed1; st1++,st2++) {        if(a[st1]>a[st2])return 0;        if(a[st2]>a[st1])return 1;    }    return 0;}int main() {    scanf("%d",&n);    scanf("%s",a+1);    for(int i=1; i<=n; i++) {        for(int j=1; j<i; j++) {            if(a[i-j+1]!='0') {                dp[i][j]=dp[i-1][j-1];                if(!check(i-j-j+2,i-j+1))                    dp[i][j]=(dp[i][j]+dp[i-j][j-1])%P;                if(check(i-j-j+1,i-j+1))                    dp[i][j]=(dp[i][j]+dp[i-j][j])%P;            }        }        dp[i][i]=1;    }    int ans=0;    for(int i=1; i<=n; i++)        ans=(ans+dp[n][i])%P;    printf("%d",ans);    return 0;}

P100

O(n2).
lcp优化.

CODE
#include<cstdio>#include<iostream>#define N 3005#define P 1000000007#define "register" is nonexistentusing namespace std;char a[N];int dp[N][N],lcp[N][N];int n;bool check(int st1,int st2) {    int ed1=st2-1;    int len=lcp[st2][st1];    if(len+st1>ed1)return 0;    return a[st1+len]<a[st2+len];}int main() {    scanf("%d",&n);    scanf("%s",a+1);    for(int i=n; i>=1; i--)        for(int j=i; j>=1; j--)            if(a[i]==a[j])lcp[i][j]=lcp[i+1][j+1]+1;            else lcp[i][j]=0;    for(int i=1; i<=n; i++) {        for(int j=1; j<i; j++) {            if(a[i-j+1]!='0') {                dp[i][j]=dp[i-1][j-1];                if(!check(i-j-j+2,i-j+1))                    dp[i][j]=(dp[i][j]+dp[i-j][j-1])%P;                if(check(i-j-j+1,i-j+1))                    dp[i][j]=(dp[i][j]+dp[i-j][j])%P;            }        }        dp[i][i]=1;    }    int ans=0;    for(int i=1; i<=n; i++)        ans=(ans+dp[n][i])%P;    printf("%d",ans);    return 0;}

T3

P100

CODE

引用自Komachi大佬.

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<cmath>using namespace std;#define REP(i,a,b) for(int i=(a),i##_END_=(b);i<i##_END_;i++)inline void Max(int &x,int y) {if(x<y)x=y;}void Rd(int &x) {    x=0;char c;    while(c=getchar(),c<48);    do x=(x<<3)+(x<<1)+(c&15);    while(c=getchar(),c>47);}#define M 100004#define K 20#define INF 0x3f3f3f3fint n,m;#define LREP(i,A) for(int i=Head[A];i;i=Next[i])int Next[M<<1],V[M<<1],Head[M],tot;void addedge(int u,int v) {Next[++tot]=Head[u],V[Head[u]=tot]=v;}int Dis[M],Fa[M],LT,RT;void Find(int A,int f,int &t) {    Dis[A]=Dis[f]+1;    Fa[A]=f;    if(Dis[A]>Dis[t])t=A;    int B;    LREP(i,A)if((B=V[i])!=f)        Find(B,A,t);}bool Use[M];int Mx[M],Dep[M],Fr[M];int RMQ1[M][K],RMQ2[M][K];int Query(int a,int b,int RMQ[M][K]) {    if(a>b)return -INF;    int k=31-__builtin_clz(b-a+1);    return max(RMQ[a][k],RMQ[b-(1<<k)+1][k]);}void FindMx(int A,int f,int fr) {    int B;    Fr[A]=fr;    Dep[A]=Dep[f]+1;    Max(Mx[fr],Dep[A]);    LREP(i,A)if((B=V[i])!=f&&!Use[B])        FindMx(B,A,fr);}int main() {    Rd(n);    REP(i,1,n) {        int u,v;        Rd(u),Rd(v);        addedge(u,v);        addedge(v,u);    }    Rd(m);    LT=RT=0;    Dis[0]=Dep[0]=-1;    Find(1,0,LT);    Find(LT,0,RT);    int p=RT;    while(p) {        Use[p]=1;        p=Fa[p];    }    p=RT;    while(p) {        FindMx(p,0,p);        RMQ1[Dis[p]][0]=Dis[p]+Mx[p];        RMQ2[Dis[p]][0]=Mx[p]-Dis[p];        p=Fa[p];    }    REP(k,1,K)REP(i,0,Dis[RT]+1) {        int j=i+(1<<k-1);        if(j>Dis[RT])break;        RMQ1[i][k]=max(RMQ1[i][k-1],RMQ1[j][k-1]);        RMQ2[i][k]=max(RMQ2[i][k-1],RMQ2[j][k-1]);    }    while(m--) {        int x,y,u,v,Ans=0;        Rd(x),Rd(y);        u=Fr[x],v=Fr[y];        if(Dis[u]>Dis[v])swap(u,v),swap(x,y);        Ans=max(min(Dep[x]+Dis[u],Dep[y]+Dis[v]),min(Dep[y]+Dis[RT]-Dis[v],Dep[x]+Dis[RT]-Dis[u]));        int pos=Dep[y]-Dep[x]+Dis[u]+Dis[v]>>1;        Max(Ans,Query(Dis[u]+1,min(Dis[v]-1,pos),RMQ1)-Dis[u]+Dep[x]);        Max(Ans,Query(max(Dis[u],pos)+1,Dis[v]-1,RMQ2)+Dis[v]+Dep[y]);        printf("%d\n",Ans);    }    return 0;}
原创粉丝点击