日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UOJ最强跳蚤

發布時間:2024/4/15 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UOJ最强跳蚤 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Problem

給一顆樹,邊有邊權。求經過的邊權積為完全平方數的路徑條數。

\(n<1e5,a_i<1e8\)

Solution

emm

可以看出要用點分治。

可是桶不好開。

所以要考慮轉換。

我們可以將任意一個數X這樣表示。

\(X = p_1^{a_1}\* p_2^{a_2} \* p_3^{a_3}\) ......

\(p\) 為質數。

然后我們給所有\(p_i\) 賦一個隨機值\(h(p_i)\)

定義 \(F(X)\) 為所有 \(a_i為奇數的h(p_i)的異或和\)

所以,我們可以得到。

當且僅當 \(F(x) = 0\) 時,\(x\) 為完全平方數。

所以我們可以把 \(A,B\) 兩數的積用 \(F(A)\oplus F(B)\) 表示,因為我們僅需要知道一個數是否為完全平方數。

然后這題就完了。

好吧,還有一些細節。

比如 \(h(p_i)\) 的隨機值要是 \(long~long\) 范圍的。這樣才能保證正確性。

還有,因為 \(a_i<1e8\) 不能用線性篩,所以我們要篩出 \(1e4\) 以內的質數,然后對所有數用 \(\frac {\sqrt a_i}{\ln n}\) 的復雜度算出 \(F(a_i)\)

還有一點很重要,桶不能用 \(map\) ,只能用 \(hash\)

先上一份自己打的,但是被 \(hack\) 數據卡T了的代碼:

#pragma GCC optimize(2) #pragma G++ optimize(2) #pragma GCC optimize(3) #pragma G++ optimize(3) #include <bits/stdc++.h>using namespace std;#define fst first #define snd second #define SZ(u) ((int) (u).size()) #define ALL(u) (u).begin(), (u).end()template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; } template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; } template<typename T> inline T read() {register T sum(0), fg(1);register char ch(getchar());for(; !isdigit(ch); ch = getchar()) if(ch == '-') fg = -1;for(; isdigit(ch); ch = getchar()) sum = (sum << 3) + (sum << 1) - 48 + ch;return sum * fg; }typedef long long LL; typedef pair<int, LL> pii; const int Maxn = 1e5 + 10, Maxv = 1e4 + 10, mod = 2333333; vector <pii> Map[Maxn]; unordered_map <LL, LL> mp,book; int pre[Maxn], top, Top, siz[Maxn], n; bool vis[Maxn],bk[Maxn + 10]; long long p[Maxn] ,del[Maxn], pre_rand[Maxn + 10], stk[Maxn], ans; LL Rand(){int res = rand(),res2 = rand();LL tmp = 1ll * res * res2;while(tmp <= 0) {if(res > res2) swap(res,res2);res = rand();tmp = 1ll * res * res2;}return tmp; } vector<pii> h[mod + 10]; int ask(LL number){int now = number % mod;for (int i = h[now].size() - 1;i >= 0; --i){if(h[now][i].snd == number)return h[now][i].fst;}return 0; } void add(LL number, int d){int now = number % mod;bool fl = 1;for (int i = h[now].size() - 1;i >= 0; --i){if(h[now][i].snd == number)h[now][i].fst += d,fl = 0;}if(fl)h[now].push_back((pii){d,number}); } void init(){srand(19260817);for (int i = 2;i <= Maxv; ++i){if(!bk[i]){pre[++Top] = i;pre_rand[Top] = Rand();for (int j = i << 1; j <= Maxv; j += i) bk[j] = 1;}} } void div_siz(int now, int pa){siz[now] = 1;for (int i = Map[now].size() - 1; i >= 0; --i){int nxt = Map[now][i].fst;if(vis[nxt] || nxt == pa)continue;div_siz(nxt, now);siz[now] += siz[nxt];} } int div_rt(int now,int pa, int tot_siz){bool fg = 1;for (int i = Map[now].size() - 1; i >= 0; --i){int nxt = Map[now][i].fst;if(vis[nxt] || nxt == pa)continue;int p = div_rt(nxt,now,tot_siz);if(p) return p;if((siz[nxt] << 1) > tot_siz) fg = 0;}if((tot_siz - siz[now] << 1) > tot_siz) fg = 0;if(fg) return now;return 0; } LL get_p(int number){LL res = 0;for (int i = 1; i <= Top && pre[i] <= number; ++i){while(number % pre[i] == 0){res ^= pre_rand[i];number /= pre[i];}}if (number > 1){if (!mp[number]){ mp[number] = Rand();}res ^= mp[number];}return res; } void get_dis(int now, int pa){stk[++top] = p[now];for (int i = Map[now].size() - 1; i >= 0; --i){int nxt = Map[now][i].fst;if(vis[nxt] || nxt == pa)continue;p[nxt] = p[now] ^ Map[now][i].snd;get_dis(nxt, now);} } void calc(int now){int tot = 0;for (int i = Map[now].size() - 1; i >= 0; --i){int nxt = Map[now][i].fst;if(vis[nxt]) continue;top = 0;p[nxt] = Map[now][i].snd;get_dis(nxt, now);for (int j = 1; j <= top; ++j){ans += ask(stk[j]);}for (int j = 1; j <= top; ++j)add(stk[j], 1), del[++tot] = stk[j];}for (int i = 1; i <= tot; ++i)add(del[i], -1); } void div_solve(int now){div_siz(now, 0), now = div_rt(now, 0, siz[now]), calc(now);vis[now] = 1;for (int i = Map[now].size() - 1; i >= 0; --i){int nxt = Map[now][i].fst;if(!vis[nxt]) div_solve(nxt);} } int main() { #ifndef ONLINE_JUDGEfreopen("a.in", "r", stdin);freopen("a.out", "w", stdout); #endifn = read<int>();init();for (int i = 1; i < n; ++i){int x = read<int>(), y = read<int>(), w = read<int>();LL w0 = get_p(w);Map[x].push_back((pii){y, w0});Map[y].push_back((pii){x, w0});}add(0,1);div_solve(1);printf("%lld\n",2ll * ans);return 0; }

這份代碼,卡了半年常,就是卡不過。

后來把手寫哈希換成hash_table就過了。

感謝fatesky大佬的幫助!!!

#include <bits/stdc++.h>using namespace std;#define fst first #define snd second #define SZ(u) ((int) (u).size()) #define ALL(u) (u).begin(), (u).end()template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; } template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; } template<typename T> inline T read() {register T sum(0), fg(1);register char ch(getchar());for(; !isdigit(ch); ch = getchar()) if(ch == '-') fg = -1;for(; isdigit(ch); ch = getchar()) sum = (sum << 3) + (sum << 1) - 48 + ch;return sum * fg; }typedef long long LL; typedef pair<int, LL> pii; const int Maxn = 1e5 + 10, Maxv = 1e4 + 10, mod = 2333333; vector <pii> Map[Maxn]; map <LL, LL> mp,book; int pre[Maxn], top, Top, siz[Maxn], n; bool vis[Maxn],bk[Maxn + 10]; long long p[Maxn],del[Maxn], pre_rand[Maxn + 10], stk[Maxn], ans; LL Rand(){int res = rand(),res2 = rand();LL tmp = 1ll * res * res2;while(tmp <= 0) {if(res > res2) swap(res,res2);res = rand();tmp = 1ll * res * res2;}return tmp; }#include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp>using namespace __gnu_pbds;namespace DIV {cc_hash_table<LL, int> H;void init(){srand(19260817);for (int i = 2;i <= Maxv; ++i){if(!bk[i]){pre[++Top] = i;pre_rand[Top] = Rand();for (int j = i << 1; j <= Maxv; j += i) bk[j] = 1;}}}void div_siz(int now, int pa){siz[now] = 1;for (int i = Map[now].size() - 1; i >= 0; --i){int nxt = Map[now][i].fst;if(vis[nxt] || nxt == pa)continue;div_siz(nxt, now);siz[now] += siz[nxt];}}int div_rt(int now,int pa, int tot_siz){ #define p zjmsbbool fg = 1;for (int i = Map[now].size() - 1; i >= 0; --i){int nxt = Map[now][i].fst;if(vis[nxt] || nxt == pa)continue;int p = div_rt(nxt,now,tot_siz);if(p) return p;if((siz[nxt] << 1) > tot_siz) fg = 0;}if((tot_siz - siz[now]) * 2 > tot_siz) fg = 0;if(fg) return now;return 0; #undef p}LL get_p(int number){LL res = 0;for (int i = 1; i <= Top && pre[i] <= number; ++i){while(number % pre[i] == 0){res ^= pre_rand[i];number /= pre[i];}}if (number > 1){if (!mp[number]) mp[number] = Rand();res ^= mp[number];}return res;}void get_dis(int now, int pa){stk[++top] = p[now];for (int i = Map[now].size() - 1; i >= 0; --i){int nxt = Map[now][i].fst;if(vis[nxt] || nxt == pa)continue;p[nxt] = p[now] ^ Map[now][i].snd;get_dis(nxt, now);}}void calc(int now){H.clear();++H[0];int tot = 0;for (int i = Map[now].size() - 1; i >= 0; --i){int nxt = Map[now][i].fst;if(vis[nxt]) continue;top = 0;p[nxt] = Map[now][i].snd;get_dis(nxt, now);for (int j = 1; j <= top; ++j) if(H.find(stk[j]) != H.end()) ans += H[stk[j]];for (int j = 1; j <= top; ++j) ++H[stk[j]];}}void div_solve(int now){div_siz(now, 0), now = div_rt(now, 0, siz[now]), calc(now);vis[now] = 1;for (int i = Map[now].size() - 1; i >= 0; --i){int nxt = Map[now][i].fst;if(!vis[nxt]) div_solve(nxt);}} } using namespace DIV;int main() { #ifndef ONLINE_JUDGEfreopen("zjm.in", "r", stdin);freopen("zjm.out", "w", stdout); #endifn = read<int>();init();for (int i = 1; i < n; ++i){int x = read<int>(), y = read<int>(), w = read<int>();LL w0 = get_p(w);Map[x].emplace_back(y, w0);Map[y].emplace_back(x, w0);}div_solve(1);printf("%lld\n",2ll * ans);return 0; }

轉載于:https://www.cnblogs.com/LZYcaiji/p/10397871.html

總結

以上是生活随笔為你收集整理的UOJ最强跳蚤的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。