Codeforces Round #138 (Div. 1)

A

记得以前做过 当时好像没做对 就是找个子串 满足括号的匹配 []最多的

开两个栈模拟 标记下就行

 1 #include <iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdio>
 5 #include<stdlib.h>
 6 #include<cmath>
 7 #include<vector>
 8 #include<queue>
 9 #include<stack>
10 using namespace std;
11 #define N 100010
12 char s[N];
13 char st[N];
14 int sn[N][3];
15 int main()
16 {
17     int i,k,top=0;
18     cin>>s;
19     k = strlen(s);
20     sn[0][0] = -1;sn[0][2] = -1;
21     for(i = 0 ;i < k ;i++)
22     {
23         if(s[i]=='('||s[i]=='[')
24          {
25              st[++top] = s[i];
26              sn[top][0] = i;
27              sn[top][1] = 0;
28              sn[top][2] = i;
29          }
30         else
31         {
32             if(s[i]==')')
33             {
34                 if(top&&st[top]=='(')
35                 {
36                    top--;
37                    sn[top][1] += sn[top+1][1];
38                    sn[top][2] = i;
39                 }
40                 else
41                 {
42                     st[++top] = s[i];
43                     sn[top][0] = i;
44                     sn[top][1] = 0;
45                     sn[top][2] = i;
46                 }
47             }
48             else
49             {
50                 if(top&&st[top]=='[')
51                 {
52                    top--;
53                    sn[top][1] += sn[top+1][1]+1;
54                    sn[top][2] = i;
55                 }
56                 else
57                 {
58                     st[++top] = s[i];
59                     sn[top][0] = i;
60                     sn[top][1] = 0;
61                     sn[top][2] = i;
62                 }
63             }
64         }
65     }
66     int maxz=0,x=0;
67     for(i = 0 ; i <= top ; i++)
68     {
69         if(maxz<sn[i][1])
70         {
71             maxz = sn[i][1];
72             x = i;
73         }
74     }
75     cout<<maxz<<endl;
76     for(i = sn[x][0]+1 ; i <= sn[x][2] ; i++)
77     cout<<s[i];
78     puts("");
79     return 0;
80 }
View Code

这题。。描述的很抽象。 按我的话来说 就是对于每一个s[i]总能找到一个子串包含它 而且与t串相等 t串还必须包含了s串的所有字母

做法:开个标记数组 标记每个字母向前以及向后最大的匹配位置 是否大于等于t串的长度

 1 #include <iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdio>
 5 #include<stdlib.h>
 6 #include<cmath>
 7 #include<vector>
 8 #include<queue>
 9 #include<stack>
10 using namespace std;
11 #define N 200010
12 char s[N],t[N];
13 int o[N],f[27],w[N];
14 int main()
15 {
16     int i,j,k,tk;
17     while(cin>>s)
18     {
19         memset(o,0,sizeof(o));
20         memset(w,0,sizeof(w));
21         memset(f,0,sizeof(f));
22         k = strlen(s);
23         cin>>t;
24         tk = strlen(t);
25         for(i = tk-1 ; i >= 0 ; i--)
26         {
27             f[t[i]-'a'] = 1;
28         }
29         for(i = k-1 ; i >= 0 ; i--)
30         {
31             if(!f[s[i]-'a']) break;
32         }
33         if(i!=-1||s[0]!=t[0])
34         {
35             puts("No");
36             continue;
37         }
38         j = 0 ;
39         for(i = 0 ; i < k ;i++)
40         {
41             if(s[i]==t[j])
42             {
43                 j++;
44                 o[i] = j;
45                 f[s[i]-'a'] = j;
46             }
47             else
48             {
49                 o[i] = f[s[i]-'a'];
50             }
51         }
52         memset(f,0,sizeof(f));
53         j = tk-1;
54         for(i = k-1 ; i >=0 ;i--)
55         {
56             if(s[i]==t[j])
57             {
58                 j--;
59                 w[i] = tk-1-j;
60                 f[s[i]-'a'] = tk-1-j;
61             }
62             else
63             {
64                 w[i] = f[s[i]-'a'];
65             }
66         }
67         for(i = 0 ; i < k ;i++)
68         {
69             if(o[i]+w[i]<=tk) break;
70             //cout<<o[i]<<" "<<w[i]<<endl;
71         }
72         if(i==k)
73         puts("Yes");
74         else  puts("No");
75     }
76     return 0;
77 }
View Code

 C 数论题

无奈数论太差 研究题解研究了好久。。可以推公式 我把具体的推法写一下 具体公式是对于第i个数来说 k次转换的结果 是 c(k+j-1,j)个a[j]之和 (j<=i) 就是当前的数 是由多个个a[j]组成的

比如 a[i]都为1  n为5 吧  初始为 1 1 1 1 1

就可以推了 k=1时  第一个数  1     =1           k = 2  第一个数  1     =1                                 ===》 1

         第二个数   1 1 (代表1个a[1] 1个a[j]) =2                 第二个数   2 1          (代表2个a[1] 1个a[j]) =3      ===》  3 1

         第三个数   1 1 1          = 3      +(2,1)  ===>            第三个数   3 2 1          = 6                                ===》  6 3 1

         第四个数 1 1 1 1        = 4      +(3,2,1) ====>        第四个数 4 3 2 1        = 10                                  ====》 10 6 3 1

         第五个数   1 1 1 1 1      =5      +(4,3,2,1)====>      第五个数   5 4 3 2 1     = 15                                =====》  15 10 6 3 1  

差不多基本可以看下了 题解说可以看出规律为。。。 说实话我没看出来。。。  不过我验证了它的规律。。。 对于k此操作 对应的用去a[j]的个数 为o[j] = c(k+j-1,j);

注意这里不要用反  例如上面最后一组 是15个a[0] 10个a[1]..1个a[4]  

另外一些数论的知识 因为涉及到组合数 又涉及到取余 所以涉及到了逆元  对于除法的逆元  a/b = ab^-1%mod   b^-1为其逆元 

逆元又涉及到一递推公式  i的逆元 nv[i]=(-MOD/i*nv[MOD%i]);    验证:两边同乘i nv[i]*i = (-mod/i*nv[mod%i])*i;     逆元性质 a*nv[a]%MOD=1 1 = (-mod/i)*i*1/(mod%i)

so i*(-MOD/i) == (MOD%i)%MOD 

-(MOD-MOD%i) == (MOD%i)%MOD  这个式子显然成立  证完

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<stdlib.h>
 6 #include<vector>
 7 #include<cmath>
 8 #include<queue>
 9 #include<set>
10 using namespace std;
11 #define N 2010
12 const double eps = 1e-8;
13 const double pi = acos(-1.0);
14 const double inf = ~0u>>2;
15 #define LL long long
16 #define mod 1000000007
17 LL a[N],v[N],o[N];
18 LL cn(int n,int m)
19 {
20     int i;
21     LL s = 1;
22     for(i = 1 ; i <= m ;i++)
23     {
24         s = ((s*v[i])%mod*(n-i+1))%mod;//除法取余 乘其逆元
25     }
26     return s;
27 }
28 int main()
29 {
30     int i,j,n,k;
31     cin>>n>>k;
32     for(i = 0; i < n ; i++)
33     cin>>a[i];
34     if(k==0)
35     {
36         for(i = 0 ; i< n ;i++)
37         cout<<a[i]<<" ";
38         puts("");
39         return 0;
40     }
41     v[0] = v[1] = 1;
42     for(i = 2; i < n ; i++)
43     v[i] = ((-mod/i*v[mod%i])%mod+mod)%mod;
44     for(i = 0 ; i < n ;i++)
45     {
46         o[i] = cn(i+k-1,i);
47     }
48     for(i = 0 ; i < n; i++)
49     {
50         LL ans=0;
51         for(j = 0 ;  j <= i ; j++)
52         ans=(ans+a[j]*o[i-j])%mod;
53         cout<<ans<<" ";
54     }
55     puts("");
56     return 0;
57 }
View Code
原文地址:https://www.cnblogs.com/shangyu/p/3564179.html