P4213 【模板】杜教筛(Sum)
杜教筛用于在亚线性时间内求出积性函数的前缀和。复杂度
详见笔记。
#include <bits/stdc++.h>
#define d(x) cerr << #x << " => " << x << endl
#define dd(x) cerr << #x << endl
#define D cerr << "Passed [" << __FUNCTION__ << "] on line " << __LINE__ << endl
#define ms(x) memset(x, 0, sizeof x)
#define int long long
using namespace std;
int rd() {
int f = 1, val = 0; char ch = getchar();
while(!isdigit(ch)) f = (ch == '-' ? -1 : 1), ch = getchar();
while(isdigit(ch)) val = val * 10 + ch - '0', ch = getchar();
return f * val;
}
void file() {
freopen("in.in", "r", stdin);
//freopen("out.out", "w+", stdout);
}
const int N = 5e6 + 6, Calced = 2e6;
int isnt[N], mu[N], phi[N], prime[N], cnt;
unordered_map<int, int> _phi, _mu;
void sieve() {
isnt[1] = isnt[0] = true;
mu[1] = 1; phi[1] = 1;
for(int i = 2; i <= Calced; i++) {
if(!isnt[i]) {
prime[++cnt] = i;
mu[i] = -1; phi[i] = i - 1;
}
for(int j = 1; j <= cnt && i * prime[j] <= Calced; j++) {
isnt[i * prime[j]] = true;
if(i % prime[j] == 0) {
mu[i * prime[j]] = 0;
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
mu[i * prime[j]] = mu[i] * mu[prime[j]];
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
for(int i = 1; i <= Calced; i++) {
mu[i] += mu[i - 1];
phi[i] += phi[i - 1];
}
}
int solve_phi(int n) {
if(n <= Calced) return phi[n];
if(_phi.count(n)) return _phi[n];
int res = n * (n + 1) / 2;
for(int l = 2; l <= n; ) {
int r = min(n / (n / l), n);
res -= (r - l + 1) * solve_phi(n / l);
l = r + 1;
}
return _phi[n] = res;
}
int solve_mu(int n) {
if(n <= Calced) return mu[n];
if(_mu.count(n)) return _mu[n];
int res = 1;
for(int l = 2; l <= n; ) {
int r = min(n / (n / l), n);
res -= (r - l + 1) * solve_mu(n / l);
l = r + 1;
}
return _mu[n] = res;
}
signed main() {
#ifdef LOCAL
file();
#endif
sieve();
int T = rd();
while(T--) {
int n = rd();
cout << solve_phi(n) << " " << solve_mu(n) << endl;
}
return 0;
}
P5357 【模板】AC自动机(二次加强版)
Trie图版。
#include <bits/stdc++.h>
#define d(x) cerr << #x << " => " << x << endl
#define dd(x) cerr << #x << endl
#define D cerr << "Passed [" << __FUNCTION__ << "] on line " << __LINE__ << endl
#define ms(x) memset(x, 0, sizeof x)
using namespace std;
int rd() {
int f = 1, val = 0; char ch = getchar();
while(!isdigit(ch)) f = (ch == '-' ? -1 : 1), ch = getchar();
while(isdigit(ch)) val = val * 10 + ch - '0', ch = getchar();
return f * val;
}
void file() {
freopen("in.in", "r", stdin);
//freopen("out.out", "w+", stdout);
}
const int N = 2e5 + 6;
struct Edge {
int to, nxt;
} Edge[N << 1];
int head[N], cnt;
void addEdge(int u, int v) {
Edge[++cnt].to = v;
Edge[cnt].nxt = head[u];
head[u] = cnt;
}
inline int idx(char c) { return c ^ 96; }
queue<int> Q;
class Aho {
public :
static const int N = ::N;
int fail[N];
class Trie {
public :
static const int N = ::N;
int tr[N][27], ed[N], cnt;
vector<int> end;
void clear() {
memset(tr, -1, sizeof tr);
end.clear();
ms(ed);
for(int i = 1; i <= 26; i++) tr[0][i] = 1;
cnt = 1;
}
Trie() {
clear();
}
void insert(char *s) {
int len = strlen(s + 1), u = 1;
for(int i = 1; i <= len; i++) {
int ch = idx(*(++s));
u = (tr[u][ch] == -1 ? (tr[u][ch] = ++cnt) : tr[u][ch]);
}
end.push_back(u);
}
} trie;
void clear() {
trie.clear();
ms(fail);
}
void build() {
fail[1] = 0;
Q.push(1);
addEdge(0, 1); addEdge(1, 0);
while(!Q.empty()) {
int u = Q.front(); Q.pop();
for(int i = 1; i <= 26; i++) {
const int v = trie.tr[u][i];
if(v == -1) {
trie.tr[u][i] = trie.tr[fail[u]][i];
continue;
}
fail[v] = trie.tr[fail[u]][i];
addEdge(v, fail[v]); addEdge(fail[v], v);
Q.push(v);
}
}
}
void match(char *s) {
int len = strlen(s + 1), u = 1;
for(int i = 1; i <= len; i++) {
u = trie.tr[u][idx(*(++s))];
// d(u);
++trie.ed[u];
}
}
} ac;
void dfs(int u, int d) {
for(int i = head[u]; ~i; i = Edge[i].nxt) {
const int v = Edge[i].to;
if(v == d) continue;
dfs(v, u);
ac.trie.ed[u] += ac.trie.ed[v];
}
}
const int M = 2e6 + 6;
char str[M], pattern[N];
signed main() {
#ifdef LOCAL
file();
#endif
int n = rd();
memset(head, -1, sizeof head);
for(int i = 1; i <= n; i++) {
scanf("%s", pattern + 1);
ac.trie.insert(pattern);
}
ac.build();
scanf("%s", str + 1);
ac.match(str);
dfs(0, 0);
for(auto it : ac.trie.end) {
printf("%d\n", ac.trie.ed[it]);
}
return 0;
}
P5610 [Ynoi2013] 大学 & 弱化版 P3987 我永远喜欢珂朵莉~
花神套路题。
因为答案为 1
一个小技巧:用并查集维护
LOJ6278 数列分块入门 2
分块套路 1.
CF76A Gift
P5304 [GXOI/GZOI2019]旅行者
CF147B Smile House
P3205 [HNOI2010]合唱队
P3999 [SHOI2013]二重镇
P3990 [SHOI2013]超级跳马
P3377 【模板】左偏树(可并堆)
P3381 【模板】最小费用最大流
P3386 【模板】二分图最大匹配
P4277 河城荷取的烟花
P5459 [BJOI2016]回转寿司
P1456 Monkey King
P1485 火枪打怪 / 【一本通 二分与三分】 手机游戏
二分。因为子弹只会对左方的妖怪造成伤害,因此优先攻击右边的妖怪。
对于一个
考虑如何高效的统计妖怪受到的溅射伤害。
注意到线性运算具有结合律。维护即可。
【一本通 二分与三分】 软件开发
CF1474D - Cleaning
考虑第一个位置,我们只能同时取走位置
取尽后,第二个位置变成了新的第一个位置。
根据这个方法,如果我们不交换,可以得到最后仅剩
另:如果交换
因此我们可以另
令
咕咕咕
此处评论已关闭