2017.10.22作业

来源:互联网 发布:百度指数数据下载 编辑:程序博客网 时间:2024/05/14 09:28

分数70(100)+100+0=170(200)

很干脆地写了前两题,可能linux环境不看好我的T1吧

题解

T1 match

先把n个真名拿来造个trie树,记录每个节点的访问次数
匹配的时候直接无脑减去节点的次数,若能减就ans++
证明如下:
对于[每种匹配],那么几个点永远都会被匹配掉,而访问次数的使用代表可行的匹配方案,无论优劣方案先后匹配对于当前节点的使用次数及上限不变
贴代码:

#include<bits/stdc++.h>using namespace std;int read(){    int x=0,f=1;char c;    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;    for(;isdigit(c);c=getchar())x=(x<<3)+(x<<1)+c-'0';    return x*f;}char s[35];int n;long long ans=0;int tot=0;struct node {    int son[28];    int num;}tr[800005];void build(char s[35]){    int len=strlen(s);    int pos=0;    for(int i=0;i<len;i++){        if(!tr[pos].son[s[i]-'a']){            tr[pos].son[s[i]-'a']=++tot;        }        pos=tr[pos].son[s[i]-'a'];        tr[pos].num++;    }}void match(char s[35]){    int len=strlen(s);    int pos=0;    for(int i=0;i<len;i++){        if(!tr[pos].son[s[i]-'a']){            break;        }        pos=tr[pos].son[s[i]-'a'];        if(tr[pos].num){            tr[pos].num--;            ans++;        }    }}int main(){//  freopen("match.in","r",stdin);//  freopen("match.out","w",stdout);    n=read();    for(int i=1;i<=n;++i){        scanf("%s",s);        build(s);    }    for(int i=1;i<=n;i++){        scanf("%s",s);        match(s);    }    cout<<ans<<endl;}

T2 pole

dp
还是想了好一会,终于发现正向dp很难,于是反向:
当插入第i根时,我们假设已插入2~i根,当前为第1根,有三种情况:
1. 插在已有队列之中,看不见
2. 插在左边,看得见
3. 插在右边,看得见
设f[i][j][k]表示当前共i根,左边看得到j根,右边看得到k根的情况
易得状态转移方程:
1. f[i][j][k]=f[i1][j][k](i2)
2. f[i][j][k]=f[i1][j1][k]
3. f[i][j][k]=f[i1][j][k1]
综上:

f[i][j][k]=f[i1][j][k](i2)+f[i1][j1][k]+f[i1][j][k1]

剩下的就简单了,预处理后时间复杂度上就也好过了

#include<bits/stdc++.h>#define m(a) memset(a,0,sizeof(a))using namespace std;int read(){    int x=0,f=1;char c;    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;    for(;isdigit(c);c=getchar())x=(x<<3)+(x<<1)+c-'0';    return x*f;}#define mod 998244353;long long f[205][205][205];void work(){    m(f);    f[1][1][1]=1;    for(int i=2;i<=200;i++){        for(int j=1;j<=i;j++){            for(int k=1;k+j<=i+1;k++){                if(j-1){                    f[i][j][k]+=f[i-1][j-1][k];                    f[i][j][k]%=mod;                }                if(k-1){                    f[i][j][k]+=f[i-1][j][k-1];                    f[i][j][k]%=mod;                }                f[i][j][k]+=f[i-1][j][k]*(i-2);                f[i][j][k]%=mod;            }        }    }}int T,n,l,r;int main(){//  freopen("pole.in","r",stdin);//  freopen("pole.out","w",stdout);    work();    T=read();    while(T--){        n=read();l=read();r=read();        cout<<f[n][l][r]<<endl;    }}

T3 tree

原创粉丝点击