• 10-17(day2)


    这次写day2的总结

    T1:表达式

    题面:给你一串表达式

    在本题中,我们对合法表达式定义如下:
    1. 任何连续(至少1个)数字是合法表达式;
    2. 若x是合法表达式,则(x)也是合法表达式;
    3. 若x和y 是合法表达式,则x+y、x-y、x*y、x/y都是合法表达式;
    4. 若x是合法表达式,则在x 前后添加任意数量的空白符也是合法表达式。
    现在给你若干个表达式,请你判断这些表达式是否是合法的。

    emmmm,写一个类似于区间dp的东西就行啦(的确定复合NOIPday2T2的难度的,但是好麻烦的感觉)

    emmmmm自己没有来得及改自己的wa程序,借用学长的ac程序

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define ll long long
    #define up(i,j,n)    for (int i = j; i <= n; i++)
    #define down(i,j,n)    for (int i = j; i >= n; i--)
    #define cmax(a,b)    a = max (a, b)
    #define cmin(a,b)    a = min (a, b)
    #define FILE        "expr"
    
    const int MAXN = 55;
    const int oo = 0x3f3f3f3f;
    
    int T, N;
    char s[MAXN];
    int vaild[MAXN][MAXN];
    
    bool isop(char o){
        if (o == '+') return 1;
        if (o == '-') return 1;
        if (o == '*') return 1;
        if (o == '/') return 1;
        return 0;
    }
    
    bool allempty(int le, int ri){
        up (i, le, ri) if (s[i] != ' ') return 0;
        return 1;
    }
    
    bool chk(int le, int ri){
        if (vaild[le][ri] != -1)     return vaild[le][ri];
        if (le > ri)             return vaild[le][ri] = 0;
        if (allempty(le, ri))         return vaild[le][ri] = 0;
        vaild[le][ri] = 0;
        bool allnumber = 1;
        up (i, le, ri) if (s[i] < '0' || s[i] > '9') {
            allnumber = 0;
            break;
        }
        if (allnumber) return vaild[le][ri] = 1;
        if (le == ri) return vaild[le][ri] = 0;
        if (s[le] == '(' && s[ri] == ')') return vaild[le][ri] = chk(le + 1, ri - 1);
        bool ok[MAXN];
        up (i, le, ri) ok[i] = 0;
        up (i, le, ri) if (isop(s[i])) {
            if (chk(le, i - 1)) ok[i - 1] |= 1;
            up (j, le + 1, i - 1) if (isop(s[j]) && ok[j - 1])
                ok[i - 1] |= chk(j + 1, i - 1);
        }
        up (i, le + 1, ri) if (isop(s[i]) && ok[i - 1])
            vaild[le][ri] |= chk(i + 1, ri);
        int lower = le - 1, upper = ri + 1;
        while (s[lower + 1] == ' ') lower++;
        while (s[upper - 1] == ' ') upper--;
        vaild[le][ri] |= chk(lower + 1, upper - 1);
        return vaild[le][ri];
    }
    
    int main(){
        freopen(FILE".in", "r", stdin);
        freopen(FILE".out", "w", stdout);
        scanf("%d", &T);
        char ch = getchar();
        while (T--) {
            gets(s);
            N = strlen(s);
            up (i, 0, N - 1) up (j, i, N - 1) vaild[i][j] = -1;
            puts(chk(0, N - 1) ? "Yes" : "No");
        }
        return 0;
    }

    T2:食物链

    emmmmm省选题还行

    题面:给你一些捕食关系,求有多少条食物链

    emmmm一A?类似于拓扑序的东西,我把每一个当前入度为零的点所连的边的权设成1,每次去边就往下传递值,最后一个点就是答案。

    #include<bits/stdc++.h>
    #define mode 1000000007
    using namespace std;
    map<string,int> a;
    int m;
    struct node
    {
        int y;
        int next;
    }b[300009];
    int lv[100009];
    int n;
    int sum;
    int f[100009];
    int op[100009];
    int vl[100009];
    int q[100009];
    int num;
    
    void init()
    {
        cin>>m;
        memset(lv,0,sizeof(lv));
        memset(op,0,sizeof(op));
        for(int i=1;i<=m;i++)
        {
            string x;
            string y;
            cin>>x>>y;
            if(a[x]==0)
                a[x]=++n;
            if(a[y]==0)
                a[y]=++n;
            b[++sum].y=a[y];
            b[sum].next=f[a[x]];
            f[a[x]]=sum;
            lv[a[y]]++;
            vl[a[x]]++;
        }
        num=n;
    }
    
    void topsort(int x)
    {
        q[1]=x;
        op[x]=1;
        int tou=0,wei=1;
        while(tou<wei)
        {
            tou++;
            int t=q[tou];
            for(int i=f[t],y;i;i=b[i].next)
            {
                lv[y=b[i].y]--;
                op[y]=(op[y]+op[t])%mode;
                if(lv[y]==0)q[++wei]=y;
            }
        }
        cout<<op[wei]<<endl;
    }
    
    int main()
    {
        freopen("chain.in","r",stdin);
        freopen("chain.out","w",stdout);
        init();
        for(int i=1;i<=n;i++)
            if(lv[i]==0)b[++sum].y=i,b[sum].next=f[n+1],f[n+1]=sum,lv[i]++;
        for(int i=1;i<=n;i++)
            if(vl[i]==0)b[++sum].y=n+2,b[sum].next=f[i],f[i]=sum,lv[n+2]++;
        topsort(n+1);
        int yu=0;
        /*for(int i=1;i<=n;i++)
            if(vl[i]==0)yu=(op[i]+yu)%mode;
        cout<<yu<<endl;*/
    }

    T3:emmmm学长说是出烂的题了

    题面:从(0,0)走到(n,m)有多少种走法,其中有k个点是坏点,不能通过。

    山神讲过的题,把每个坏点排序,x为第一关键字,y第二关键字,从小到大,

    设dp[i]表示到第i个坏点且不经过其他坏点的总方案数,新增加一个点(n,m),则dp[k]为所求答案。

    则有状态转移方程dp[i] = C[x[i]+y[i],x[i]) - sum(dp[j] * C(x[i] - x[j] + y[i] - y[j],x[i] - x[j])

    那么问题就是快速求组合数了,容我智障,数论0基础,不会求

    学长教了一种o(n)预处理,o(1)查询的求组合数的方法。

    int C(int a, int b){
            if (a < 0 || b < 0 || a < b) return 0;
            return mul(fac[a], mul(inv[b], inv[a - b]));
    }
    void Prepare(){
        scanf("%d%d%d", &N, &M, &K);
        up (i, 1, K) scanf("%d%d", &a[i].fi, &a[i].se);
        a[++K] = make_pair(N, M);
        sort(a + 1, a + K + 1);
        fac[0] = 1; inv[1] = 1; inv[0] = 1;
        up (i, 1, LIM) fac[i] = mul (i, fac[i - 1]);
        up (i, 2, LIM) inv[i] = mul (mod - mod / i, inv[mod % i]);
        up (i, 1, LIM) cmul(inv[i], inv[i - 1]);
    }
  • 相关阅读:
    JDBC提高mysql入库的效率!
    Java域名解析,类似nslookup
    request.getReader()的怪异事件
    程序一部署上就占了tomcat的2G内存
    nginx简介及简单使用
    ubuntu安装hadoop(伪分布)
    .Net Famework 和 Library的源码下载
    将switch case转为条件驱动
    Asp.net 和 Comet 开发入门, 第一个例子
    HTML, CSS和Javascript调试入门
  • 原文地址:https://www.cnblogs.com/assassinyyd/p/7683352.html
Copyright © 2020-2023  润新知