Codeforces Round #338 (Div. 2)

水 A- Bulbs

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e5 + 5;
const int INF = 0x3f3f3f3f;
bool vis[110];

int main(void)	{
	memset (vis, false, sizeof (vis));
	int n, m;	scanf ("%d%d", &n, &m);
	for (int i=1; i<=n; ++i)	{
		int x;	scanf ("%d", &x);
		for (int j=1; j<=x; ++j)	{
			int y;	scanf ("%d", &y);
			if (!vis[y])	vis[y] = true;
		}
	}
	bool flag = true;
	for (int i=1; i<=m; ++i)	{
		if (!vis[i])	{
			flag = false;	break;
		}
	}
	if (flag)	puts ("YES");
	else	puts ("NO");

	return 0;
}

DFS+DP B - Longtail Hedgehog

题意:找一条递增的链,最后一个点的度数乘链的长度最大。

分析:DFS写搓了,记忆化搜索dp能优化复杂度,也可以直接两个for贪心解决。本以为不会有极端的数据的。。。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e5 + 5;
const int M = 2e5 + 5;
const int INF = 0x3f3f3f3f;
vector<int> G[N];
int dp[N];
bool vis[N];
int n, m;

int DFS(int u)	{
    if (dp[u])  return dp[u];
    dp[u] = 1;
	for (int i=0; i<G[u].size (); ++i)	{
		int v = G[u][i];
		if (v < u)  dp[u] = max (dp[u], DFS (v) + 1);
	}
    return dp[u];
}

ll run(void)	{
	fill (dp+1, dp+1+n, 0);
	ll ret = 0;
	for (int i=1; i<=n; ++i)	{
		ret = max (ret, 1ll * DFS (i) * (int) G[i].size ());
	}
	return ret;
}

int main(void)	{
	scanf ("%d%d", &n, &m);
	for (int u, v, i=1; i<=m; ++i)	{
		scanf ("%d%d", &u, &v);
		G[u].push_back (v);
		G[v].push_back (u);
	}
	printf ("%I64d
", run ());

	return 0;
}

  

组合数学 D - Multipliers

题意:给定m个质因子p[],有p[1]*p[2]*...*p[m] == n,问n所有因子的乘积 % 1e9 + 7。

分析:m个质因子可能有重复的,n = p[i] ^ k[i],k[i]表示p[i]在乘积里贡献了几次,k[i] = (num[i] * (num[i] + 1)) / 2 * (num[j] + 1) (i != j);也就是p[j]可能出现有0,1,2...num[j]。由费马小定理:a ^ x = a ^ (x % (p - 1)) (mod p),k[i]能变形成:(num[i] / 2) * (num[j] + 1),但是p - 1不是质数,不能用求2的逆元,可以用mod2 = 2 * (1e9 + 7) ???

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 2e5 + 5;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int MOD2 = 2ll * (MOD - 1);
int m;
int p[N], num[N];

int pow_mod(int x, ll n, int mod)	{
	int ret = 1;
	while (n)	{
		if (n & 1)	ret = 1ll * ret * x % mod;
		x = 1ll * x * x % mod;	n >>= 1;
	}
	return ret;
}

int main(void)	{
	scanf ("%d", &m);
	for (int i=1; i<=m; ++i)	{
		scanf ("%d", &p[i]);
		num[p[i]]++;
	}
	sort (p+1, p+1+m);
	int n = unique (p+1, p+1+m) - p - 1;
	int tot = 1;
	for (int i=1; i<=n; ++i)	{
		tot = 1ll * tot * (num[p[i]] + 1) % MOD2;
	}
	int ans = 1;
	for (int i=1; i<=n; ++i)	{
		ans = 1ll * ans * pow_mod (p[i], 1ll * num[p[i]] * tot / 2, MOD) % MOD;
	}
	printf ("%d
", ans);

	return 0;
}

  

Trie || KMP C - Running Track

题意:给s和t字符串,问最少的分割t的子串来自s,输出起点和终点

分析:贪心的想法,每次求最长的子串,可以用字典树来查找也可以直接用KMP

Trie

#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> P;
typedef long long ll;
const int N = 2100 + 5;
const int INF = 0x3f3f3f3f;
struct Trie	{
	int ch[N*N][26], sz;
	P pr[N*N];
	int idx(char c)	{
		return c - 'a';
	}
	void clear(void)	{
		sz = 1;	memset (ch[0], 0, sizeof (ch[0]));
	}
	void insert(char *str, int from, int dr)	{
		int u = 0;
		for (int c, i=from; i>=0&&str[i]; i+=dr)	{
			c = idx (str[i]);
			if (!ch[u][c])	{
				memset (ch[sz], 0, sizeof (ch[sz]));
				ch[u][c] = sz++;
			}
			u = ch[u][c];
			pr[u] = make_pair (from, i);
		}
	}
	void query(char *str, vector<P> &vec)	{
		int u = 0;
		for (int c, i=0; str[i]; ++i)	{
			c = idx (str[i]);
			if (!ch[u][c])	{
				if (u == 0)	{
					vec.clear ();	return ;
				}
				vec.push_back (pr[u]);	u = 0;	i--;
			}
			else	u = ch[u][c];
		}
		vec.push_back (pr[u]);
	}
}trie;
char s[N], t[N];

int main(void)	{
	scanf ("%s%s", &s, &t);
	trie.clear ();
	for (int i=0; s[i]; ++i)	{
		trie.insert (s, i, 1);
		trie.insert (s, i, -1);
	}
	vector<P> ans;
	trie.query (t, ans);
	if (ans.size () == 0)	{
		puts ("-1");	return 0;
	}
	printf ("%d
", (int) ans.size ());
	for (int i=0; i<ans.size (); ++i)	{
		printf ("%d %d
", ans[i].first + 1, ans[i].second + 1);
	}

	return 0;
}

KMP

#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> P;
typedef long long ll;
const int N = 2100 + 5;
const int INF = 0x3f3f3f3f;
char s[N], rs[N], t[N];
int fail[N];

void get_fail(char *P, int lenp)	{
	int i = 0, j = -1;	fail[0] = -1;
	while (i < lenp)	{
		if (j == -1 || P[j] == P[i])	{
			i++;	j++;	fail[i] = j;
		}
		else	j = fail[j];
    }
}

P KMP(char *T, char *P)	{
	int lent = strlen (T), lenp = strlen (P);
	get_fail (P, lenp);
	int i = 0, j = 0, max_len = 0, beg = -1;
	while (i < lent)	{
		while (j != -1 && T[i] != P[j])	j = fail[j];
		i++;	j++;
		if (j > max_len)	{
			max_len = j;	beg = i - j;
		}
		if (j == lenp)	break;
	}
	return make_pair (beg, beg + max_len - 1);
}

bool add_answer(P p1, P p2, vector<P> &ans, int len, int &i)	{
	P ap = p1, bp = make_pair (len - p2.first - 1, len - p2.second - 1);
    int la = p1.second - p1.first, lb = p2.second - p2.first;
    if (p1.first == -1)	{
		if (p2.first == -1)	return false;
		ans.push_back (bp); i += lb;
	}
    else if (p2.first == -1)    {
        if (p1.first == -1) return false;
        ans.push_back (ap); i += la;
    }
    else    {
        if (la > lb)    {
            ans.push_back (ap); i += la;
        }
        else    {
            ans.push_back (bp); i += lb;
        }
    }
    return true;
}

int main(void)	{
	scanf ("%s%s", &s, &t);
	int lens = strlen (s), lent = strlen (t);
	for (int i=0; i<lens; ++i)	rs[i] = s[lens-i-1];
	vector<P> ans;
    for (int i=0; i<lent; ++i)	{
		P pr1 = KMP (s, t + i);
		P pr2 = KMP (rs, t + i);
		if (!add_answer (pr1, pr2, ans, lens, i))	{
			puts ("-1");	return 0;
		}
	}
	printf ("%d
", (int) ans.size ());
	for (int i=0; i<ans.size (); ++i)	{
		printf ("%d %d
", ans[i].first + 1, ans[i].second + 1);
	}

	return 0;
}

  

编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/5118992.html