暴力分又没骗满sad.....

Problem A 走路

  $O(n^2)$动态规划是显然的。

  更新方式有两种:一种是枚举它的倍数转移,一种是转移到它的约数。

  考虑利用分块来平衡一下(像分块FWT一样)。

  注意到若$x = ab, y = cd, (a, b) = 1, (c, d) = 1$,那么$x | y$的充分必要条件是$a | c, b | d$或者$a | d, b | c$。

  那么我们可以把$v_1$拆成$AB, (A, B) = 1$,使得$A$和$B$的约数个数尽量相等。

  对于每一部分,离散化后暴力处理整除关系。每次修改或查询时固定一维动另一维。

  时间复杂度$O(nV^{0.25})$。

Code

 #include <algorithm>
#include <iostream>
#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <ctime>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean; #define ll long long
#define ull unsigned long long template <typename T>
T add(T a, T b, T m) {
return ((a += b) >= m) ? (a - m) : (a);
} template <typename T>
T sub(T a, T b, T m) {
return ((a -= b) < ) ? (a + m) : (a);
} template <typename T>
void pcopy(T* pst, const T* ped, T* pval) {
for ( ; pst != ped; *(pst++) = *(pval++));
} template <typename T>
void pfill(T* pst, const T* ped, T val) {
for ( ; pst != ped; *(pst++) = val);
} ll mul(ll a, ll b, ll m) {
// return (__int128)a * b % m;
ll rt = , pa = a;
for ( ; b; b >>= , pa = add(pa, pa, m))
if (b & )
rt = add(rt, pa, m);
return rt;
} ll qpow(ll a, ll p, ll m) {
ll rt = , pa = a;
for ( ; p; p >>= , pa = mul(pa, pa, m))
if (p & )
rt = mul(rt, pa, m);
return rt;
} ll gcd(ll a, ll b) {
return (b) ? (gcd(b, a % b)) : (a);
} ll randLL() {
static ull seed = , msk = (1ull << ) - ;
return (signed ll) ((seed = seed * seed + seed + ) & msk);
} int pri[] = {, , , , , , , }; boolean miller_rabin(ll n) {
static int T = ;
for (int i = ; i < ; i++)
if (!(n % pri[i]))
return n == pri[i];
if (n < ) {
for (int p = ; p * p <= n; p++)
if (!(n % p))
return false;
return true;
}
ll d = n - ;
int s = ;
while (!(d & ))
s++, d >>= ;
for (int t = ; t < T; t++) {
ll b = randLL() % n;
if (!b)
continue;
ll tmp = qpow(b, d, n);
if (tmp == || tmp == n - )
continue;
for (int i = ; i < s; i++) {
tmp = mul(tmp, tmp, n);
if (tmp == n - )
goto nextTurn;
if (tmp == || tmp == )
return false;
}
if (tmp != )
return false;
nextTurn:;
}
return true;
} ll pollard_rho(ll x) {
ll a, b, c, g;
if (!(x & ))
return ;
while (true) {
b = a = randLL() % x;
c = randLL() % ;
do {
a = add(mul(a, a, x), c, x);
b = add(mul(b, b, x), c, x);
b = add(mul(b, b, x), c, x);
g = gcd(b - a, x);
(g < ) ? (g = -g) : ();
if (g == x)
break;
if (g > )
return g;
} while (a != b);
}
assert(false);
return ;
} void get_primary_factors(ll x, vector<ll>& rt) {
if (miller_rabin(x)) {
rt.push_back(x);
return;
}
ll a = pollard_rho(x);
get_primary_factors(a, rt);
get_primary_factors(x / a, rt);
} vector< pair<ll, int> > get_primary_factor(vector<ll>& vec) {
vector< pair<ll, int> > rt;
if (vec.empty())
return rt;
sort(vec.begin(), vec.end());
vector<ll>::iterator it = vec.begin();
rt.push_back(make_pair(*it, ));
for (it = it + ; it != vec.end(); it++)
if (*it == rt.back().first)
rt.back().second++;
else
rt.push_back(make_pair(*it, ));
return rt;
} typedef vector< pair<ll, int> > factor; /// Template ends template <typename T>
class Matrix {
public:
T* p;
int r, c; Matrix() : p(NULL) { }
Matrix(int r, int c) : r(r), c(c) {
p = new T[r * c];
} T* operator [] (int pos) {
return p + c * pos;
}
}; const int Mod = 1e9 + ; int n;
ll *v;
int *f;
Matrix<int> F;
vector<int> *g;
vector<ll> va, vb;
vector<int> *diva, *divb, *mula, *mulb; inline void init() {
scanf("%d", &n);
g = new vector<int>[(n + )];
for (int i = , u, v; i < n; i++) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
v = new ll[(n + )];
for (int i = ; i <= n; i++)
scanf(Auto, v + i);
} ll A = , B;
int *a, *b; inline void discrete() {
vector<ll> _fac;
get_primary_factors(v[], _fac);
factor fac = get_primary_factor(_fac); random_shuffle(fac.begin(), fac.end()); a = new int[(n + )];
b = new int[(n + )];
ll da = , db = ;
for (auto p : fac)
db *= (p.second + );
for (auto p : fac) {
// cerr << p.first << " " << p.second << '\n';
if (da * (p.second + ) <= db / (p.second + )) {
da *= (p.second + ), db /= (p.second + );
for (int j = ; j < p.second; j++)
A *= p.first;
}
}
B = v[] / A;
// cerr << da << " " << db << '\n'; for (int i = ; i <= n; i++)
va.push_back(gcd(v[i], A));
for (int i = ; i <= n; i++)
vb.push_back(gcd(v[i], B)); sort(va.begin(), va.end());
sort(vb.begin(), vb.end());
va.erase(unique(va.begin(), va.end()), va.end());
vb.erase(unique(vb.begin(), vb.end()), vb.end()); // cerr << va.size() << ' ' << vb.size() << '\n';
F = Matrix<int>(va.size(), vb.size());
pfill(F[], F[va.size()], );
for (int i = ; i <= n; i++) {
a[i] = lower_bound(va.begin(), va.end(), gcd(v[i], A)) - va.begin();
b[i] = lower_bound(vb.begin(), vb.end(), gcd(v[i], B)) - vb.begin();
} diva = new vector<int>[va.size()];
divb = new vector<int>[vb.size()];
mula = new vector<int>[va.size()];
mulb = new vector<int>[vb.size()];
for (int i = ; i < (signed) va.size(); i++) {
for (int j = ; j < (signed) va.size(); j++) {
if (!(va[i] % va[j]))
diva[i].push_back(j);
if (!(va[j] % va[i]))
mula[i].push_back(j);
}
}
for (int i = ; i < (signed) vb.size(); i++) {
for (int j = ; j < (signed) vb.size(); j++) {
if (!(vb[i] % vb[j]))
divb[i].push_back(j);
if (!(vb[j] % vb[i]))
mulb[i].push_back(j);
}
}
} void dp(int p, int fa) {
if (p == ) {
f[p] = ;
} else {
for (auto x : mulb[b[p]])
f[p] = add(f[p], F[a[p]][x], Mod);
}
for (auto x : diva[a[p]])
F[x][b[p]] = add(F[x][b[p]], f[p], Mod);
for (auto e : g[p])
if (e ^ fa)
dp(e, p);
for (auto x : diva[a[p]])
F[x][b[p]] = sub(F[x][b[p]], f[p], Mod);
} inline void solve() {
f = new int[(n + )];
pfill(f + , f + n + , );
dp(, );
for (int i = ; i <= n; i++)
printf("%d\n", f[i]);
} int main() {
srand((unsigned) time (NULL));
init();
discrete();
solve();
return ;
}

Problem A

Problem B 走路

  显然,使得$(1, 1)$和$(n, n)$不连通的方案斜着放车。

  然后随便容斥一下,得到:

$ans = n! - 2\sum_{i = 1}^{n}(n - i)! + 1 + \sum_{s = 2}^{n}(s - 1)(n - s)!$

  发现需要阶乘,阶乘的前缀和以及阶乘的前缀和前缀和。

  不会。分块大表。

  laofu把数压成若干可见字符的方法真高级。

  (请手动打表)

Code

 #include <iostream>
#include <cstdio>
using namespace std;
typedef bool boolean; const int n = 1e7, Mod = 1e9 + ; int add(int a, int b) {
return ((a += b) >= Mod) ? (a - Mod) : (a);
} int sub(int a, int b) {
return ((a -= b) < ) ? (a + Mod) : (a);
} int mul(int a, int b) {
return (a * 1ll * b) % Mod;
} void exgcd(int a, int b, int& x, int& y) {
if (!b)
x = , y = ;
else {
exgcd(b, a % b, y, x);
y -= (a / b) * x;
}
} int inv(int a, int n) {
int x, y;
exgcd(a, n, x, y);
return (x < ) ? (x + n) : (x);
} int fac[n + ];
int sfac[n + ];
int ssfac[n + ];
int ans[n + ]; inline void init() {
fac[] = ;
for (int i = ; i <= n; i++)
fac[i] = mul(fac[i - ], i);
sfac[] = ;
for (int i = ; i <= n; i++)
sfac[i] = add(sfac[i - ], fac[i]);
ssfac[] = ;
for (int i = ; i <= n; i++)
ssfac[i] = add(ssfac[i - ], sfac[i]);
// ans[1] = ans[2] = 0, ans[3] = 2;
// int reduce =
// for (in ti = 4; i <= n; i++) {
// ans[i] = add(ans[i - 1], fac[i]);
// ans[i] = sub(ans[i], fac[i - 1]);
// ans[i] = sub(ans[i], mul(fac[i - 1], 2));
// ans[i] = add(ans[i], )
// }
} inline void solve() {
int T, n;
// cerr << fac[300000] << " " << sfac[300000] << " " << ssfac[300000] << '\n';
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
// int ans = fac[n];
// for (int i = 1; i <= n; i++)
// ans = sub(sub(ans, fac[n - i]), fac[n - i]);
// ans = add(ans, 1);
// for (int s = 2; s <= n; s++)
// ans = add(ans, mul(s - 1, fac[n - s]));
int ans = ((n <= ) ? : add(fac[n], ));
if (n > ) {
ans = sub(ans, mul(sfac[n - ], ));
ans = add(ans, ssfac[n - ]);
}
printf("%d\n", ans);
}
} int main() {
init();
solve();
return ;
}

Problem B

Problem C 有趣的字符串题

  好像SD有道是这道题的强制在线的版本,之前有人讲过分块做法。然后就一直陷入了分块的漩涡中。sad....

  正解是考虑右端点在$r$的时候,询问左端点在每个位置时的答案。

  考虑移动右端点至$r + 1$时产生的贡献。显然我们只用考虑它的回文border。

  考虑一些长度构成等差数列的border。

  对于每一段讨论它会产生贡献的部分。注意向前移动周期个字符的情形以及前一个这中间的最长串的前一个的出现的位置$[x, y]$。

  若$z$是这些串中最短的一个串出现的左端点。不难得到当左端点在整数区间$(x, z]$中时,会有贡献。

  对于不同的这样的border,显然每一组可以单独计算贡献。

  因此我们用一个树状数组维护这个贡献,用线段树维护最后的出现位置,再用回文树维护border,就完事了。

  时间复杂度$O(n\log^2n + m\log n)$。

Code

 #include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <map>
using namespace std;
typedef bool boolean; template <typename T>
void pfill(T* pst, const T* ped, T val) {
for ( ; pst != ped; *(pst++) = val);
} typedef class Input {
protected:
const static int limit = ;
FILE* file; int ss, st;
char buf[limit];
public: Input():file(NULL) { };
Input(FILE* file):file(file) { } void open(FILE *file) {
this->file = file;
} void open(const char* filename) {
file = fopen(filename, "r");
} char pick() {
if (ss == st)
st = fread(buf, , limit, file), ss = ;//, cerr << "str: " << buf << "ed " << st << endl;
return buf[ss++];
}
}Input; #define digit(_x) ((_x) >= '0' && (_x) <= '9') Input& operator >> (Input& in, unsigned& u) {
char x;
while (~(x = in.pick()) && !digit(x));
for (u = x - ''; ~(x = in.pick()) && digit(x); u = u * + x - '');
return in;
} Input& operator >> (Input& in, unsigned long long& u) {
char x;
while (~(x = in.pick()) && !digit(x));
for (u = x - ''; ~(x = in.pick()) && digit(x); u = u * + x - '');
return in;
} Input& operator >> (Input& in, int& u) {
char x;
while (~(x = in.pick()) && !digit(x) && x != '-');
int aflag = ((x == '-') ? (x = in.pick(), -) : ());
for (u = x - ''; ~(x = in.pick()) && digit(x); u = u * + x - '');
u *= aflag;
return in;
} Input& operator >> (Input& in, long long& u) {
char x;
while (~(x = in.pick()) && !digit(x) && x != '-');
int aflag = ((x == '-') ? (x = in.pick(), -) : ());
for (u = x - ''; ~(x = in.pick()) && digit(x); u = u * + x - '');
u *= aflag;
return in;
} Input& operator >> (Input& in, char* str) {
for (char x; ~(x = in.pick()) && x != '\n' && x != ' '; *(str++) = x);
} Input in (stdin); const int alpha = ; typedef class TrieNode {
public:
int len, dif, g;
int in, out, id;
map<char, TrieNode*> ch;
TrieNode *fail, *slink;
}TrieNode; typedef class PalindromeTree {
public:
int len;
TrieNode *pool;
TrieNode *top;
TrieNode *odd, *even;
TrieNode *last;
TrieNode **node;
char *str; TrieNode* newnode(int len) {
top->id = top - pool;
top->len = len, top->dif = -, top->g = ;
// memset(top->ch, 0, sizeof(top->ch));
top->fail = top->slink = NULL;
return top++;
} PalindromeTree() { }
PalindromeTree(int n) {
node = new TrieNode*[(n + )];
pool = new TrieNode[(n + )];
str = new char[(n + )];
top = pool, len = ;
odd = newnode(-), even = newnode();
odd->fail = odd, even->fail = odd;
odd->dif = even->dif = -, last = even, str[] = ;
} TrieNode* extend(TrieNode* p) {
while (str[len - p->len - ] != str[len]) p = p->fail;
return p;
} void append(char x) {
str[++len] = x;
int c = x - 'a';
last = extend(last);
if (!last->ch[c]) {
TrieNode* p = newnode(last->len + );
p->fail = extend(last->fail)->ch[c];
if (!p->fail)
p->fail = even;
last->ch[c] = p;
p->dif = p->len - p->fail->len; if (p->dif == p->fail->dif)
p->slink = p->fail->slink;
else
p->slink = p->fail;
}
last = last->ch[c];
node[len] = last;
} void build(vector<int>* g) {
for (TrieNode* p = pool; p != top; p++) {
if (p->fail && p->fail != p) {
g[p->fail->id].push_back(p->id);
g[p->id].push_back(p->fail->id);
}
}
} TrieNode* operator [] (int p) {
return node[p];
}
}PalindromeTree; typedef class Query {
public:
int l, r, id; boolean operator < (Query p) const {
return r < p.r;
}
}Query; typedef class SegTreeNode {
public:
int val;
SegTreeNode *l, *r; SegTreeNode() : val(), l(NULL), r(NULL) { } void pushUp() {
val = max(l->val, r->val);
}
}SegTreeNode; const int N = 3e5 + ; SegTreeNode pool[N << ];
SegTreeNode *top = pool; SegTreeNode *newnode() {
return top++;
} typedef class SegTree {
public:
int n;
SegTreeNode* rt; SegTree() : rt(NULL) { }
SegTree(int n) : n(n) {
build(rt, , n);
} void build(SegTreeNode*& p, int l, int r) {
p = newnode();
if (l == r)
return ;
int mid = (l + r) >> ;
build(p->l, l, mid);
build(p->r, mid + , r);
} void modify(SegTreeNode *p, int l, int r, int idx, int val) {
if (l == r) {
p->val = val;
return ;
}
int mid = (l + r) >> ;
if (idx <= mid)
modify(p->l, l, mid, idx, val);
else
modify(p->r, mid + , r, idx, val);
p->pushUp();
} int query(SegTreeNode* p, int l, int r, int ql, int qr) {
if (l == ql && r == qr)
return p->val;
int mid = (l + r) >> ;
if (qr <= mid)
return query(p->l, l, mid, ql, qr);
if (ql > mid)
return query(p->r, mid + , r, ql, qr);
int a = query(p->l, l, mid, ql, mid);
int b = query(p->r, mid + , r, mid + , qr);
return (a > b) ? (a) : (b);
} void modify(int idx, int val) {
modify(rt, , n, idx, val);
} int query(int ql, int qr) {
return query(rt, , n, ql, qr);
}
}SegTree; typedef class IndexedTree {
public:
int s;
int *a; IndexedTree() { }
IndexedTree(int n) : s(n) {
a = new int[(n + )];
pfill(a, a + n + , );
} void add(int idx, int val) {
for ( ; idx <= s; idx += (idx & (-idx)))
a[idx] += val;
} void add(int l, int r, int val) {
add(l, val), add(r + , -val);
} int query(int idx) {
int rt = ;
for ( ; idx; idx -= (idx & (-idx)))
rt += a[idx];
return rt;
}
}IndexedTree; const int Mod = 1e9 + ; int add(int a, int b) {
return ((a += b) >= Mod) ? (a - Mod) : (a);
} int sub(int a, int b) {
return ((a -= b) < ) ? (a + Mod) : (a);
} int mul(int a, int b) {
return a * 1ll * b % Mod;
} int n, m;
char *s;
Query* qs;
SegTree st;
vector<int> *g;
IndexedTree it;
PalindromeTree pt; inline void init() {
in >> n >> m;
s = new char[(n + )];
qs = new Query[(m + )];
pt = PalindromeTree(n + );
g = new vector<int>[(n + )];
in >> s;
for (int i = ; i < n; i++)
pt.append(s[i]);
delete[] s;
pt.build(g);
for (int i = ; i <= m; i++)
in >> qs[i].l >> qs[i].r, qs[i].id = i;
} int dfs_clock;
void dfs(int p, int fa) {
pt.pool[p].in = ++dfs_clock;
// cerr << p << " " << fa << '\n';
for (auto e : g[p])
if (e ^ fa)
dfs(e, p);
pt.pool[p].out = dfs_clock;
} int res = ;
inline void solve() {
st = SegTree(n + );
it = IndexedTree(n);
dfs(, -);
sort(qs + , qs + m + ); Query* q = qs + , *qed = qs + m + ;
for (int i = ; i <= n; i++) {
for (TrieNode *p = pt[i]; p && p->len; p = p->slink) {
int left = max(st.query(p->in, p->out) - p->len + , ) + ;
int right = i - p->dif - ((p->slink) ? (p->slink->len) : ()) + ;
// cerr << i << " " << left << " " << right << '\n';
it.add(left, right, );
}
st.modify(pt[i]->in, i);
while (q != qed && q->r == i) {
res = add(res, mul(it.query(q->l), q->id));
// cerr << "Q: " << it.query(q->l) << " " << q->id << '\n';
q++;
}
}
printf("%d\n", res);
} int main() {
init();
solve();
return ;
}

Problem C

湖南省队集训 Day 2的更多相关文章

  1. [2018湖南省队集训] 6.24 T1 marshland

    题面在这里! 一开始感觉像一个类似二分图的最小割,于是成功跑偏2333333 很容易发现一个关键性质,'L'的两个角落在的偶数格 的行(或者列)的奇偶性一定不同.... 于是我们再把偶数格按照行(或者 ...

  2. [2018湖南省队集训] 6.28 T3 simulate

    这道模拟题出的我毫无脾气2333 最重要的是先要发现操作顺序不影响最后的答案,也就是每次随便挑一个>=2的数进行操作最后总是可以得到同样的数列. (这个还不太难想qwq) 但是最骚的是接下来的模 ...

  3. [2018湖南省队集训] 6.28 T2 color

    毒瘤计数题2333,(小声)k其实可以出到1e9,不过这样求组合数的时候就要记1000种数的1~1000次下降幂(用到的组合数中第一维在1e9级别的只有1000种左右,第二维都是<=1000), ...

  4. JS省队集训记

    不知不觉省队集训已经结束,离noi也越来越近了呢 论考前实战训练的重要性,让我随便总结一下这几天的考试 Day 1 T1 唉,感觉跟xj测试很像啊?meet in middle,不过这种题不多测是什么 ...

  5. [2018HN省队集训D9T1] circle

    [2018HN省队集训D9T1] circle 题意 给定一个 \(n\) 个点的竞赛图并在其中钦定了 \(k\) 个点, 数据保证删去钦定的 \(k\) 个点后这个图没有环. 问在不删去钦定的这 \ ...

  6. [2018HN省队集训D8T1] 杀毒软件

    [2018HN省队集训D8T1] 杀毒软件 题意 给定一个 \(m\) 个01串的字典以及一个长度为 \(n\) 的 01? 序列. 对这个序列进行 \(q\) 次操作, 修改某个位置的字符情况以及查 ...

  7. [2018HN省队集训D8T3] 水果拼盘

    [2018HN省队集训D8T3] 水果拼盘 题意 给定 \(n\) 个集合, 每个集合包含 \([1,m]\) 中的一些整数, 在这些集合中随机选取 \(k\) 个集合, 求这 \(k\) 个集合的并 ...

  8. [2018HN省队集训D6T2] girls

    [2018HN省队集训D6T2] girls 题意 给定一张 \(n\) 个点 \(m\) 条边的无向图, 求选三个不同结点并使它们两两不邻接的所有方案的权值和 \(\bmod 2^{64}\) 的值 ...

  9. [Luogu P4143] 采集矿石 [2018HN省队集训D5T3] 望乡台platform

    [Luogu P4143] 采集矿石 [2018HN省队集训D5T3] 望乡台platform 题意 给定一个小写字母构成的字符串, 每个字符有一个非负权值. 输出所有满足权值和等于这个子串在所有本质 ...

随机推荐

  1. HMAC-SHA256 签名方法各个语音的实现方式之前端JavaScriptes6

    sha256和16进制输出,网上很多种后端的验证方法,几乎没有前端的,所以自己写了个,希望给类似需求的人一个帮助,适用场景 腾讯云接口鉴权 v3签名 npm install sha256npm ins ...

  2. Enterprise Architect

    Enterprise Architect 是一款计算机辅助软件工程,这款软件用于设计和构建软件系统.业务流程建模及更多通用的建模.EA不同于普通的UML画图工具(如VISIO),它将支撑系统开发的全过 ...

  3. Python request SSL证书问题

    错误信息如下: 1 requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'tls_process_s ...

  4. [转]k8s核心概念

    转载自 https://blog.csdn.net/real_myth/article/details/78719244 什么是kubernetes 首先,他是一个全新的基于容器技术的分布式架构领先方 ...

  5. python生成数据后,快速导入数据库

    1.使用python生成数据库文件内容 # coding=utf-8import randomimport time def create_user():    start = time.time() ...

  6. sessionStorage 前端HTML5会话管理

    sessionStorage 是在HTML5中新增的一个会话存储对象,sessionStorage 用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据.. 提示: 如果你想 ...

  7. python装饰器扩展之functools.wraps

    我们知道函数被装饰器,装饰后,所有的属性,以及内置函数就失效了. 原因是函数类型变成了warpper类型 示例1:不带wraps装饰器示例 def warfunc(func): def warpper ...

  8. 关于11G DataGuard 日志传输的案例

    案例探讨 在归档和非归档模式下,配置参数log_archive_dest_2后,DG的备库是否传输日志. 案例环境描述 本次环境如下,一套RAC+单机DG,然后从DG还原出来一个单独的测试库A,测试库 ...

  9. 取模性质,快速幂,快速乘,gcd和最小公倍数

    一.取模运算 取模(取余)运算法则: 1. (a+b)%p=(a%p+b%p)%p; 2.(a-b)%p=(a%p-b%p)%p; 3.(a*b)%p=(a%p * b%p)%p; 4.(a^b)%p ...

  10. React组件绑定this的三种方法

    我们在使用React组件时,调用方法常常用到this和event对象,默认情况是不会绑定到组件上的,需要特殊处理. 节点上使用bind绑定 特点:该方法会在每次渲染组件时都会重新绑定一次,消耗一定的性 ...