Codeforces Round #138 (Div. 1)
A
记得以前做过 当时好像没做对 就是找个子串 满足括号的匹配 []最多的
开两个栈模拟 标记下就行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
B
这题。。描述的很抽象。 按我的话来说 就是对于每一个s[i]总能找到一个子串包含它 而且与t串相等 t串还必须包含了s串的所有字母
做法:开个标记数组 标记每个字母向前以及向后最大的匹配位置 是否大于等于t串的长度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
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 这个式子显然成立 证完
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }