-
CF785D
计数
http://codeforces.com/contest/785/problem/D
题解 :
- 非常有意思的一道题,求一段括号序列中RSBS的个数,但有个关键点必须事先知道不然无法做。
- 对于前x个为左括号后y个为右括号的序列,它的RSBS为( x x+y )
- 若指定某个左括号为RSBS序列最后的左括号,他在原序列中前面有x-1个左括号,后面有y个右括号,则这样的RSBS序列有(xx+y-1)个。
- 详情见http://codeforces.com/blog/entry/50996
- 1到n n个数的逆元可以O(n)求, 通过(b<sup >a)可以O(1)求(b+1a+1)和(ba-1), 综上复杂度为O(n);
代码
#include<cstdio>
typedef long long ll;
const int MAXN = 2e5+1e3;
const int MOD = 1e9+7;
ll ans = 0, cur;
ll inv[MAXN];
char s[MAXN];
int n, x, y, a;
int main() {
scanf("%s", s);
inv[0] = 0;
inv[1] = 1;
for(int i=2; i<MAXN; ++i)
inv[i] = -inv[MOD%i]*(MOD/i)%MOD;
x = y = n = 0;
for(char *p=s; *p; ++p) {
if(*p==')') ++y;
++n;
}
a = x+y-1;
cur = 1;
for(int i=0; i<n&&y; ++i) {
if(s[i]=='(') {
++a, ++x;
cur = cur*a%MOD*inv[x]%MOD;
ans = (ans+cur)%MOD;
}
else {
cur = cur*(a-x)%MOD*inv[a]%MOD;
--a, --y;
if(!y) break;
}
}
if(ans<0) ans+=MOD;
printf("%I64d\n", ans);
return 0;
}
-
topcoder SRM 710 div2 C
图论, 最大最小
Problem Statement
You are given an undirected graph with n nodes and m edges. The nodes are labeled from 0 to n-1. This graph is guaranteed to be connected and have no self-loops or multiple edges.
You are given a description of the graph: the vector <int>s a, b, w, and v. For each valid i, there is an edge that connects nodes a[i] and b[i] and has weight w[i]. For each valid j, node j has weight v[j]. All weights are positive integers.
A path in this graph is a sequence of pairwise distinct nodes such that each pair of consecutive nodes is connected by an edge. The difficulty of a path is the value (N times E), where N is the maximum weight of a node on the path (including the nodes where it starts and ends) and E is the maximum weight of an edge on the path.
For each pair of distinct nodes i and j, let d(i,j) be the smallest possible difficulty of a path that connects i and j. Find and return the sum of d(i,j) with 0 ≤ i < j ≤ n-1.
题解:
有几点
1. 最大的点值最小的路径不一定与最大边值最小的路径相同
2. a到b有多条路径, b到c有1条路,a到b的最优解不一定被包含在a到c的最优解。
3. 一个解法为,枚举每个点,假设他为路径上点值最大的点,找到点值小于等于他的点,包含他所构成的连通分量,在进行算,复杂度O(n^4).
代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 312;
typedef pair<int,int> pii;
int dbg = 0;
class MinMaxMax
{
long long d[MAXN][MAXN];
int fa[MAXN];
bool alive[MAXN];
vector<pii> su, se;
vector<int> sa, sb;
int n, m;
public:
int getfa(int x) {
if(x==fa[x]) return x;
return fa[x]=getfa(fa[x]);
}
long long findMin(vector <int> a,
vector <int> b,
vector <int> w,
vector <int> v) {
m = a.size();
n = v.size();
su.clear();
se.clear();
int i, j;
i=0; for(auto e: w)
se.push_back(make_pair(e, i++));
i=0; for(auto u: v)
su.push_back(make_pair(u, i++));
sort(su.begin(), su.end());
sort(se.begin(), se.end());
memset(d, 0x3f, sizeof(d));
for(auto u:su) {
for(i=0; i<n; ++i) fa[i] = i;
for(auto ui:su)
alive[ui.second] = (ui.first<=u.first);
for(auto e:se) {
int s=a[e.second], t=b[e.second];
if(!alive[s]||!alive[t]) continue;
s=getfa(s); t=getfa(t);
if(s==t) continue;
sa.clear(); sb.clear();
for(i=0; i<=n; ++i) {
if(getfa(i)==s) sa.push_back(i);
else if(getfa(i)==t) sb.push_back(i);
}
long long cur = 1ll*e.first*u.first;
for(auto ai:sa)
for(auto bi:sb) {
d[ai][bi] = min(d[ai][bi], cur);
d[bi][ai] = min(d[bi][ai], cur);
}
fa[s] = fa[t] = min(s,t);
}
}
long long ret = 0;
for(i=0; i<n; ++i)
for(j=i+1; j<n; ++j)
ret += d[i][j];
return ret;
}
};
FZU-2128
AC自动机
https://vjudge.net/problem/FZU-2128
题解: 上个月做的一道AC自动机的模板题,主要是做个整理
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int MAXL = 1<<20;
const int MAXN = 1e5+1e3;
char s[MAXL];
vector<pair<int,int> > v;
struct Trie{
int ch[MAXN][26];
int val[MAXN], sz;
int last[MAXN], f[MAXN];
void clear() {
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
}
int idx(char c) {
return c-'a';
}
void insert(char* s) {
int u = 0, i;
for(i=0; s[i]; ++i) {
int c= idx(s[i]);
if(!ch[u][c]) {
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = i;
}
void print(int ed, int j) {
if(j) {
v.push_back(make_pair(ed-val[j]+1, ed));
print(ed, last[j]);
}
}
void find(char* T) {
int l = strlen(T);
int j = 0;
for(int i=0; i<l; ++i) {
int c = idx(T[i]);
while(j&&!ch[j][c]) j=f[j];
j = ch[j][c];
if(val[j]) print(i,j);
else if(last[j]) print(i, last[j]);
}
}
void getFail() {
queue<int> q;
f[0] = 0;
for(int c=0; c<26; ++c) {
int u = ch[0][c];
if(u) {
f[u] = last[u] = 0;
q.push(u);
}
}
while(!q.empty()) {
int r = q.front(); q.pop();
for(int c=0; c<26; ++c) {
int u = ch[r][c];
if(!u) continue;
q.push(u);
int v = f[r];
while(v&&!ch[v][c]) v=f[v];
f[u] = ch[v][c];
last[u] = val[f[u]]?f[u]:last[f[u]];
}
}
}
}AC;
int main() {
ios::sync_with_stdio(false);
while(cin >> s) {
char tmp[128];
int n, len;
len = strlen(s);
cin >> n;
AC.clear();
for(int i=0; i<n; ++i) {
cin >> tmp;
AC.insert(tmp);
}
AC.getFail();
v.clear();
AC.find(s);
sort(v.begin(), v.end());
int l = 0, ans=0;
for(int i=0; i<v.size(); ++i) {
ans = max(ans,v[i].second-l);
l = v[i].first+1;
}
ans = max(ans, len-l);
cout << ans << endl;
}
return 0;
}