uoj426

题意

\(n,\ N,\ m,\ x_1,\ x_2,\ ...,\ x_m,\ y_1,\ y_2,\ ...,\ y_m\)
\(\sum_{a_1=1}^N\sum_{a_2=1}^N\dots\sum_{a_n=1}^N\ \sigma_0(gcd(a_1,\ a_2,\ ...,\ a_n)^3)^3\ \Pi_{i=1}^m[a_{x_i}\leq a_{y_i}]\bmod 2^{32}\),其中 \(\sigma_0(n)\) 表示 \(n\) 的约数个数。

\(1\ \leq\ n\ \leq\ 20,\ 1\ \leq\ N\ \leq\ 10^{10},\ 1\ \leq\ m\ \leq\ n(n\ -\ 1)\)

做法1

\(ways(x)\ =\ \sum_{a_1=1}^x\sum_{a_2=1}^x\dots\sum_{a_n=1}^x\ \ \Pi_{i=1}^m[a_{x_i}\leq a_{y_i}]\bmod 2^{32}\)。则 \(ans\ =\ \sum_{d=1}^N\ \sigma_0(d^3)^3\sum_{e=1}^{\left\lfloor\frac{N}{d}\right\rfloor}\mu(e)\cdot ways(\left\lfloor\frac{N}{de}\right\rfloor)\ \\=\ \sum_{x=1}^N\ ways(\left\lfloor\frac{N}{x}\right\rfloor)\sum_{d|x}\ \sigma_0(d^3)^3\mu(\frac{x}{d})\)
\(F(n)\ =\ \sum_{d|n}\ \sigma_0(d^3)^3\mu(\frac{x}{d})\)。枚举 \(\left\lfloor\frac{N}{x}\right\rfloor\) 计算后面的式子即可。问题转化成求 \(ways(x)\)\(F(x)\) 的前缀和。

考虑用 \(min\_25\) 筛来求 \(F(x)\) 的前缀和。令 \(S(p,\ n)\ =\ \sum_{i=1}^n[i\) 的质因子都 \(\geq p] F(i)\),用滚动数组存下 \(S_p(n)\) 即可。

\(ways(x)\) 可以先求出 \(a\)\(k\) 个不同的值的方案数。求 \(a\)\(k\) 个不同值得方案数考虑状压 \(dp\),令 \(f(k,\ u,\ S)\) 表示 \(a_v\ \leq\ k\ +\ [v\leq u],\ v\in S\) 的方案数。

时间复杂度 \(O(\frac{N^{\frac{3}{4}}}{logN}\ +\ n^22^n\ +\ n\sqrt{N})\)

代码

#include <bits/stdc++.h>

#ifdef __WIN32
#define LLFORMAT "I64"
#else
#define LLFORMAT "ll"
#endif

using namespace std;

using u32 = unsigned int;

namespace graph {
	int n, m, N;
	vector<u32> res, pw2(32);

	void init() {
		pw2[0] = 1;
		for (int i = 1; i < 32; ++i) pw2[i] = pw2[i - 1] << 1;
		vector<vector<int> > g(n), rg(n);
		while(m--) {
			int u, v;
			cin >> u >> v;
			g[u - 1].push_back(v - 1);
			rg[v - 1].push_back(u - 1);
		}
		vector<bool> vis(n, false);
		vector<int> col(n, -1), ord;
		function<void(int)> dfs_ord = [&](int u) {
			vis[u] = 1;
			for (int v: g[u]) if(!vis[v]) dfs_ord(v);
			ord.push_back(u);
			return;
		};
		for (int u = 0; u < n; ++u) if(!vis[u]) dfs_ord(u);
		reverse(ord.begin(), ord.end());
		function<void(int)> dfs_col = [&](int u) {
			col[u] = N;
			for (int v: rg[u]) if(!~col[v]) dfs_col(v);
			return;
		};
		for (int u: ord) if(!~col[u]) dfs_col(u), ++N;
		vector<int> G(N, 0);
		for (int u = 0; u < n; ++u) for (int v: g[u]) if(col[u] != col[v]) G[col[v]] |= (1 << col[u]);
		int S = 1 << N;
		vector<u32> dp(S, 0), pd(S);
		dp[0] = 1;
		res = vector<u32>(N + 1, 0);
		for (int i = 1; i <= N; ++i) {
			auto foo = dp;
			for (int u = 0; u < N; ++u) {
				fill(pd.begin(), pd.end(), 0);
				u32 t;
				for (int s = 0; s < S; ++s) if(t = dp[s]) {
					pd[s] = pd[s] + t;
					if((!((s >> u) & 1)) && ((s & G[u]) == G[u])) pd[s | (1 << u)] = pd[s | (1 << u)] + t;
				}
				dp = pd;
			}
			for (int s = 0; s < S; ++s) dp[s] -= foo[s];
			res[i] = dp[S - 1];
		}
		return;
	}

	u32 Q(long long n) {
		u32 ret = 0, x = 1, y = 0;
		for (int i = 1; i <= N; ++i) {
			auto work = [&](long long n) {
				u32 y = 0;
				while(~n & 1) n >>= 1, ++y;
				return make_pair((u32)n, y);
			};

			auto inv = [&](u32 ua) {
				long long a = ua, b = 1ll << 32, x, y;
				function<void(long long, long long &, long long, long long &)> extgcd = [&](long long a, long long &x, long long b, long long &y) {
					if(!b) { x = 1; y = 0; return; }
					long long c = a / b;
					extgcd(b, y, a - c * b, x);
					y -= x * c;
					return;
				};
				extgcd(a, x, b, y);
				return (u32)x;
			};

			if(i > n) break;
			auto t = work(n - i + 1);
			x *= t.first; y += t.second;
			t = work(i);
			x *= inv(t.first); y -= t.second;

			ret += x * (y >= 32 ? 0 : pw2[y]) * res[i];
		}
		return ret;
	}
}

namespace func {
	long long N, B;
	vector<u32> s1, s2;
	constexpr u32 pool[] = {0, 1, 64, 127, 406, 469};

	void init() {
		B = floor(sqrt(1. * N)) + 10;
		while(B * B > N) --B;
		vector<bool> isp(B + 1, true);
		vector<int> pme;
		for (int x = 2; x <= B; ++x) {
			if(isp[x]) pme.push_back(x);
			for (int p: pme) {
				int y = p * x;
				if(y > B) break;
				isp[y] = 0;
				if(x % p == 0) break;
			}
		}
		vector<u32> cnt1(B + 1, 0), cnt2(N / (B + 1) + 1, 0);
		for (int x = 1; x <= B; ++x) cnt1[x] = x - 1;
		for (int x = 1; x < cnt2.size(); ++x) cnt2[x] = u32(N / x - 1);
		for (int p: pme) {
			long long q = (long long) p * p;
			u32 t = cnt1[p - 1];
			for (int x = 1; x < cnt2.size(); ++x) {
				long long n = N / x;
				if(n < q) break;
				n /= p;
				if(n <= B) cnt2[x] -= cnt1[n] - t;
				else cnt2[x] -= cnt2[x * p] - t;
			}
			for (int x = B; x >= q; --x) cnt1[x] -= cnt1[x / p] - t;
		}
		s1 = vector<u32>(cnt1.size(), 0);
		s2 = vector<u32>(cnt2.size(), 0);
		for (int _ = pme.size() - 1; ~_; --_) {
			int p = pme[_];
			long long q = (long long) p * p, qq = (_ == pme.size() - 1 ? N + 1 : (long long) pme[_ + 1] * pme[_ + 1]);
			auto S = [&](long long n) {
				if(n < qq) return n >= p ? ((n > B ? cnt2[N / n] : cnt1[n]) - cnt1[p]) * 63 : 0;
				return n > B ? s2[N / n] : s1[n];
			};
			for (int x = 1; x < cnt2.size(); ++x) {
				long long n = N / x;
				if(n < q) break;
				long long q = n / p, ret = S(n);
				int k = 1;
				while(q) {
					ret += (1 + S(q)) * (81 * k * k - 27 * k + 9);
					++k;
					q /= p;
				}
				s2[x] = ret;
			}
			for (int n = B; n >= q; --n) {
				long long q = n / p, ret = S(n);
				int k = 1;
				while(q) {
					ret += (1 + S(q)) * (81 * k * k - 27 * k + 9);
					++k;
					q /= p;
				}
				s1[n] = ret;
			}
		}
		return;
	}

	u32 Q(long long n) {
		return n <= 5 ? pool[n] : (n > B ? s2[N / n] : s1[n]) + 1;
	}
}

int main() {
	cin >> graph::n >> func::N >> graph::m;
	graph::init();
	func::init();
	u32 ans = 0;
	for (long long x = 1; x <= func::N; ++x) {
		long long y = func::N / (func::N / x);
		ans += graph::Q(func::N / x) * (func::Q(y) - func::Q(x - 1));
		x = y;
	}
	cout << ans << endl;
	return 0;
}
posted @ 2018-11-21 12:08  King_George  阅读(181)  评论(0编辑  收藏  举报