• 【自家测试】2017-12-16 FJOI2016 d1


    1. 所有公共子序列问题
    (allcs.pas/c/cpp)
    ★问题描述:
    一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序
    列X= x 1 x 2 ... x m ,则另一序列Z= z 1 z 2 ... z k 是X的子序列是指存在一个严格递增下标序列
    i 1 , i 2 ,..., i k 使得对于所有j=1,2,...,k有 z j  x ij 。例如,序列Z=GACT是序列X= GCTACT的子
    序列,相应的递增下标序列为1,4,5,6。给定2个序列X和Y,当另一序列Z既是X的子序列又是
    Y的子序列时,称Z是序列X和Y的公共子序列。例如,若X= GCTACT,Y= GATCCT,序列
    TT是X和Y的一个公共子序列,序列GACT也是X和Y的一个公共子序列。注意对于任何给定
    的序列X和Y,空序列总是它们的一个公共子序列。
    所有公共子序列问题是要求对于给定的2个序列X= x 1 x 2 ... x m 和Y= y 1 y 2 ... y n ,找出X
    和Y的所有不同的公共子序列。
    ★编程任务:
    对于给定的2个序列X= x 1 x 2 ... x m 和Y= y 1 y 2 ... y n ,根据输入数据的要求,找出它们所
    有不同的公共子序列,或计算出它们有多少个不同的公共子序列。
    ★数据输入:
    输入文件名为allcs.in。
    文件的第一行有2个正整数m和n, (1<=m,n<=3010),分别表示2个输入序列X和Y的长度。
    接下来的2行分别给出输入序列X= x 1 x 2 ... x m 和Y= y 1 y 2 ... y n 。其中序列中每个元素均为26
    个英文大小写字母。文件的最后一行给出一个非负整数k。k的值为1时,表示计算结果要输
    出X和Y的所有不同的公共子序列,以及X和Y有多少个不同的公共子序列。k的值为0时,表
    示计算结果只要输出X和Y有多少个不同的公共子序列。
    ★结果输出:
    输出文件名为allcs.out。
    将计算出的X和Y的所有不同的公共子序列,或X和Y有多少个不同的公共子序列输出到
    文件中。当k=1时,先输出X和Y的所有不同的公共子序列,每行输出1个公共子序列,按字
    典序从小到大输出。最后输出不同的公共子序列的个数。当k=0时,只要输出不同的公共子
    序列的个数。

    输入示例1
    6 6
    GCTACT
    GATCCT
    1

    输出示例1
    26
    A
    AC
    ACT
    AT
    C
    CC
    CCT
    CT
    G
    GA
    GAC
    GACT
    GAT
    GC
    GCC
    GCCT
    GCT
    GT
    GTC
    GTCT
    GTT
    T
    TC
    TCT
    TT
    26

    输入示例2
    6 6
    GCTACT
    GATCCT
    0

    输出示例2
    26

    根连向每个字母第一次出现的位置,每个位置的儿子分别连向它之后每个字母第一次出现的位置.这貌似就是传说中的序列自动机.

    在两个序列自动机同时dfs.需要输出序列则直接dfs并输出即可.

    不需要输出序列时,记忆化搜索.但是由于答案很大,需要高精.

    std又WA又T又RE,我也没有什么办法.

    70分代码.

      1 //Achen
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdlib>
      6 #include<vector>
      7 #include<cstdio>
      8 #include<queue>
      9 #include<cmath>
     10 #include<set>
     11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
     12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
     13 const int N=3017;
     14 typedef long long LL; 
     15 typedef double db;
     16 using namespace std;
     17 char a[N],b[N],prt[N];
     18 int n,m,K,ch1[N][52],ch2[N][52],ls[52];
     19 
     20 template<typename T> void read(T &x) {
     21     char ch=getchar(); x=0; T f=1;
     22     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
     23     if(ch=='-') f=-1,ch=getchar();
     24     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
     25 }
     26 
     27 void make_it(char s[],int n,int ch[][52]) {
     28     memset(ls,0,sizeof(ls));
     29     For(i,1,n) {
     30         int c=(s[i]>='a'&&s[i]<='z')?s[i]-'a':26+s[i]-'A';
     31         if(!ls[c]) ch[0][c]=i; 
     32         ls[c]=i;
     33     }
     34     memset(ls,0,sizeof(ls));
     35     Rep(i,n,1) {
     36         int c=(s[i]>='a'&&s[i]<='z')?s[i]-'a':26+s[i]-'A';
     37         For(j,0,51) ch[i][j]=ls[j];
     38         ls[c]=i;
     39     }
     40 }
     41 
     42 int dp[N][N],tot;
     43 struct G {
     44     int len;
     45     LL d[26];
     46 };
     47 
     48 const LL bs=1e17;
     49 G operator +(const G&A,const G&B) {
     50     G rs; 
     51     For(i,0,25) rs.d[i]=0;
     52     rs.len=max(A.len,B.len)+1;
     53     LL pr=0;
     54     For(i,1,rs.len) {
     55         rs.d[i]=A.d[i]+B.d[i]+pr;
     56         if(rs.d[i]>=bs) pr=1,rs.d[i]-=bs;
     57         else pr=0;
     58     }
     59     while(rs.d[rs.len]==0) rs.len--;
     60     return rs;
     61 }
     62 
     63 G ans,g[500007];
     64 
     65 G dfs(int x,int y) {
     66     if(dp[x][y]!=-1) return g[dp[x][y]];
     67     dp[x][y]=++tot;
     68     G rs; rs.len=1; 
     69     For(i,0,25) rs.d[i]=0; rs.d[1]=1;
     70     For(i,0,51) if(ch1[x][i]&&ch2[y][i]) {
     71         rs=rs+dfs(ch1[x][i],ch2[y][i]);
     72     }
     73     g[dp[x][y]]=rs; 
     74     return rs;
     75 }
     76 
     77 void PT(G a) {
     78     printf("%lld",a.d[a.len]);
     79     Rep(i,a.len-1,1) {
     80         if(a.d[i]==0) printf("0000000000000000");
     81         else {
     82             LL tp=a.d[i];
     83             while(tp*10<bs) { printf("0"); tp*=10; }
     84             printf("%lld",a.d[i]);
     85         }
     86     } printf("
    ");
     87 }
     88 
     89 int anstot;
     90 void print(int x,int y,int pos) {
     91     prt[pos]=a[x];
     92     prt[pos+1]=0;
     93     puts(prt); anstot++;
     94     For(i,0,51) if(ch1[x][i]&&ch2[y][i]) 
     95         print(ch1[x][i],ch2[y][i],pos+1);
     96 }
     97 
     98 #define DEBUG
     99 int main() {
    100 #ifdef DEBUG
    101     freopen("allcs.in","r",stdin);
    102     freopen("allcs.out","w",stdout);
    103 #endif
    104     read(n); read(m);
    105     scanf("%s",a+1);
    106     make_it(a,n,ch1);
    107     scanf("%s",b+1);
    108     make_it(b,m,ch2);
    109     read(K);
    110     memset(dp,-1,sizeof(dp));
    111     if(!K) {
    112         ans.len=1;
    113         For(i,0,25) ans.d[i]=0; ans.d[1]=1;
    114         For(i,0,51) 
    115             if(ch1[0][i]&&ch2[0][i]) 
    116                 ans=ans+dfs(ch1[0][i],ch2[0][i]);
    117         PT(ans);
    118     }
    119     if(K) {
    120         puts("");
    121         For(i,0,51) 
    122             if(ch1[0][i]&&ch2[0][i]) 
    123                 print(ch1[0][i],ch2[0][i],0);
    124         printf("%d
    ",anstot+1);
    125     }
    126     return 0;
    127 }
    View Code

    2. 建筑师
    (building.pas/c/cpp)
    ★问题描述:
    小Z是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建n个建筑,
    每个建筑的高度是1到n之间的一个整数。小Z有很严重的强迫症,他不喜欢有两个建筑的高
    度相同。另外小Z觉得如果从最左边(所有建筑都在右边)看能看到A个建筑,从最右边(所
    有建筑都在左边)看能看到B个建筑,这样的建筑群有着独特的美感。现在,小Z想知道满足
    上述所有条件的建筑方案有多少种?
    如果建筑i的左(右)边没有任何建造比它高,则建筑i可以从左(右)边看到。两种方案不
    同,当且仅当存在某个建筑在两种方案下的高度不同。
    ★数据输入:
    输入文件名为building.in。
    第一行一个整数 T,代表 T 组数据。
    接下来T行,每行三个整数n,A,B。
    ★结果输出:
    输出文件名为building.out。
    9
    对于每组数据输出一行答案 mod ( 10 ^9+ 7 ) 。

    输入示例
    2
    3 2 2
    3 1 2

    输出示例
    2
    1

    ★数据范围:
    10% : 1 <= n <= 10
    20% : 1 <= n <= 100
    40% : 1 <= n <= 50000,1 <= T <= 5
    100% :1 <= n <= 50000,1 <= A, B <= 100,1 <= T <= 200000。

    题解在这里

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<cstdio>
     7 #include<cmath>
     8 const int N=5e4+7;
     9 const int mod=1e9+7;
    10 typedef long long LL;
    11 using namespace std;
    12 LL dp[N][207],C[207][207];
    13 int T,n,a,b;
    14 
    15 template<typename T> void read(T &x) {
    16     char ch=getchar(); T f=1; x=0;
    17     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    18     if(ch=='-') f=-1,ch=getchar();
    19     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    20 }
    21 
    22 #define DEBUG
    23 int main() {
    24 #ifdef DEBUG
    25     freopen("building.in","r",stdin);
    26     freopen("building.out","w",stdout);
    27 #endif
    28     dp[1][1]=1;
    29     for(int i=2;i<=50000;i++) 
    30         for(int k=1;k<=min(200,i);k++) 
    31             dp[i][k]=(dp[i-1][k]*(i-1)%mod+dp[i-1][k-1])%mod;
    32     for(int i=0;i<=200;i++) C[i][0]=1;
    33     for(int i=1;i<=200;i++)
    34         for(int j=1;j<=i;j++)
    35             C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
    36     read(T);
    37     while(T--) {
    38         read(n); read(a); read(b);
    39         LL ans=dp[n-1][a+b-2];
    40         ans=(ans*C[a+b-2][a-1])%mod;
    41         printf("%lld
    ",ans);
    42     }
    43     return 0;
    44 }
    45 /*
    46 3 2 2
    47 2 1
    48 */
    View Code

    3. 神秘数
    (mystic.pas/c/cpp)
    ★问题描述:
    一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数。例如
    S={1,1,1,4,13},
    1 = 1
    2 = 1+1
    3 = 1+1+1
    4 = 4
    5 = 4+1
    6 = 4+1+1
    7 = 4+1+1+1
    8无法表示为集合S的子集的和,故集合S的神秘数为8。
    现给定n个正整数a[1]..a[n],m个询问,每次询问给定一个区间[l,r](l<=r),求由
    a[l],a[l+1],...,a[r]所构成的可重复数字集合的神秘数。
    ★编程任务:
    求出每个查询的结果。
    ★数据输入:
    输入文件名为mystic.in。
    第一行一个整数n,表示数字个数。
    第二行n个整数,从1编号。
    第三行一个整数m,表示询问个数。
    以下m行,每行一对整数l,r,表示一个询问。
    ★结果输出:
    输出文件名为mystic.out。
    对于每个询问,输出一行对应的答案。

    输入示例
    5
    1 2 4 9 10
    5
    1 1
    1 2
    1 3
    1 4
    1 5

    输出示例
    2
    4
    8
    8
    8

    ★数据范围:
    对于 10%的数据点,n,m <= 10
    对于 30%的数据点,n,m <= 1000
    对于 60%的数据点,n,m <= 50000
    对于 100%的数据点,n,m <= 100000,∑a[i] <= 10

    十分奥妙的一道题.

    求一段区间的神秘数,先把区间内的数从小到大排序.

    依次加入每个数x,若当前神秘数为ans

    若x>ans+1,神秘数仍为ans

    否则神秘数变为ans+x

    排序后,找到第一个大于它前面所有数的和+1的数,它前面所有数的和+1即为神秘数.

    那么求区间l,r的神秘数,先将当前神秘数ans设为1,查询区间内小于等于ans的数的和sum,若sum>ans,则ans=sum+1

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<cmath>
    10 #include<set>
    11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
    12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    13 const int N=100007;
    14 typedef long long LL; 
    15 typedef double db;
    16 using namespace std;
    17 int n,m,a[N],sz;
    18 
    19 template<typename T> void read(T &x) {
    20     char ch=getchar(); x=0; T f=1;
    21     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    22     if(ch=='-') f=-1,ch=getchar();
    23     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    24 }
    25 
    26 int tot,rt[N],sg[N*71],ls[N*71],rs[N*71];
    27 #define lc ls[x]
    28 #define rc rs[x]
    29 #define mid ((l+r)>>1)
    30 void update(int &x,int l,int r,int pos,int last) {
    31     x=++tot;
    32     sg[x]=sg[last]+pos;
    33     lc=ls[last];
    34     rc=rs[last];
    35     if(l==r) return;
    36     if(pos<=mid) update(lc,l,mid,pos,ls[last]);
    37     else update(rc,mid+1,r,pos,rs[last]);
    38 }
    39 
    40 int qry(int x,int l,int r,int ql,int qr) {
    41     if(!x) return 0;
    42     if(l>=ql&&r<=qr) return sg[x];
    43     if(qr<=mid) return qry(lc,l,mid,ql,qr);
    44     if(ql>mid) return qry(rc,mid+1,r,ql,qr);
    45     return qry(lc,l,mid,ql,qr)+qry(rc,mid+1,r,ql,qr);
    46 }
    47 
    48 #define DEBUG
    49 int main() {
    50 #ifdef DEBUG
    51     freopen("mysti.in","r",stdin);
    52     freopen("mysti.out","w",stdout);
    53 #endif
    54     read(n);
    55     For(i,1,n) { read(a[i]); sz=max(sz,a[i]); }
    56     For(i,1,n) update(rt[i],1,sz,a[i],rt[i-1]);
    57     read(m);
    58     For(i,1,m) {
    59         int l,r;
    60         read(l); read(r);
    61         int ans=1;
    62         for(;;) {
    63             int tp=qry(rt[r],1,sz,1,ans)-qry(rt[l-1],1,sz,1,ans);
    64             if(tp<ans) break;
    65             ans=tp+1;
    66         }
    67         printf("%d
    ",ans);
    68     }
    69     return 0;
    70 }
    View Code

    说不出是什么心情,只能说.道不同不相为谋吧.

     (UPD:似乎不知不觉间通往另一个end了)

  • 相关阅读:
    【JavaWeb 实际项目 03】
    【JavaWeb EL表达式&JSTL标签库 09】
    【JavaWeb jsp 08】
    【JavaWeb 实际项目 02】
    【JavaWeb Servlet 07】
    【JavaWeb Servlet 06】
    【JavaWeb xml&tomcat 05】
    【JavaWeb jQuery 04】
    【JavaWeb jQuery 03】
    【JavaWeb JavaScript 02】
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8796900.html
Copyright © 2020-2023  润新知