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]);
}

 

posted @ 2017-10-17 18:59  assassin灬  阅读(196)  评论(0编辑  收藏  举报