2017-11-3离线赛总结

题目

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 1000000007
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 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 1000000007
using 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 1000000007
using 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 1000000007
using 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 nonexistent
using 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 0x3f3f3f3f
int 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;
}
发布了34 篇原创文章 · 获赞 44 · 访问量 5075

猜你喜欢

转载自blog.csdn.net/zzyyyl/article/details/78436448
今日推荐