Luogu3307:[SDOI2013]項鍊
阿新 • • 發佈:2018-12-26
傳送門
求每個珠子的方案數
即有序的求三元組 \((x,y,z),x,y,z\le a\) 滿足 \(gcd(x,y,z)=1\)
設 \(G_i\) 表示 \(i\) 個小於等於 \(a\) 的有序數字,滿足 \(gcd=1\) 的方案數
容斥得到要求的
\[\frac{1}{6}(G_3+2G_2+3G_1)\]
然後 \(G_1=1\)
運用簡單莫比烏斯反演得到
\[G_2=\sum_{i=1}^{a}\lfloor\frac{a}{i}\rfloor^2\mu(i)\]
\[G_3=\sum_{i=1}^{a}\lfloor\frac{a}{i}\rfloor^3\mu(i)\]
求項鍊條數
運用 \(Polya\) 定理
設 \(f(x)\) 表示 \(x\) 的點的環,選擇上面求出的 \(m\) 種顏色,同色不相鄰的方案數
那麼要求的就是
\[\frac{1}{n}\sum_{i=1}^{n}f(gcd(i,n))=\frac{1}{n}\sum_{d|n}f(d)\varphi(\frac{n}{d})\]
求f
容斥不好做
樸素想法是列舉開始和結尾的顏色,顯然也不好做
考慮增量算 \(f(x)\)
首先可以斷開 \(x-1\) 的鏈
\(x-1\) 的首尾不同,貢獻為 \((m-2)f(x-1)\)
\(x-1\) 的首尾相同,貢獻為 \((m-1)f(x-2)\)
那麼 \(f(x)=(m-2)f(x-1)+(m-1)f(x-2)\)
本題應該是預設 \(f(1)=0\),
直接構造生成函式 \(F(x)=\sum_{i=0}^{x}f(i)x^i\)
那麼 \(F(x)=(m-2)F(x)x+(m-1)F(x-2)x^2+f(2)\)
所以
\[F(x)=\frac{m-1}{1-(m-1)x}-\frac{m-1}{1+x}\]
\(f(x)=(m-1)^x-(-1)^{x-1}(m-1)\)
最後
注意到 \(n\) 可能是 \(10^9+7\) 的倍數
可以考慮對 \((10^9+7)^2\) 取模
如果是倍數,初始答案算出來和 \(n\) 一起除去 \(mod\) 再求逆元即可
# include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn(1e7 + 5); const int mod(1e9 + 7); const ll dmod((ll)mod * mod); const ll inv6(833333345000000041ll); inline void Inc(ll &x, ll y) { x = x + y >= dmod ? x + y - dmod : x + y; } inline ll Mul(ll x, ll y) { return (x * y - (ll)(((long double)x * y + 0.5) / (long double)dmod) * dmod + dmod) % dmod; } inline ll Pow1(ll x, ll y) { register ll ret = 1; for (x %= mod, y %= mod - 1; y; y >>= 1, x = x * x % mod) if (y & 1) ret = ret * x % mod; return ret; } inline ll Pow2(ll x, ll y) { register ll ret = 1; for (; y; y >>= 1, x = Mul(x, x)) if (y & 1) ret = Mul(ret, x); return ret; } int test, pr[maxn / 10], tot, mu[maxn], cnt; bitset <maxn> ispr; ll n, a, ret, ans, d[maxn], ct[maxn]; inline ll Calc(ll x) { register ll v = Pow2(ret, x); (x & 1) ? Inc(v, dmod - ret) : Inc(v, ret); return v; } void Dfs(int x, ll v, ll phi) { if (x > cnt) { Inc(ans, Mul(phi, Calc(n / v))); return; } register int i; Dfs(x + 1, v, phi), v = v * d[x], phi = phi * (d[x] - 1), Dfs(x + 1, v, phi); for (i = 2; i <= ct[x]; ++i) v *= d[x], phi *= d[x], Dfs(x + 1, v, phi); } inline void Solve() { register ll i, j, x; scanf("%lld%lld", &n, &a), ans = 0, ret = 2; for (i = 1; i <= a; i = j + 1) { j = a / (a / i); Inc(ret, Mul(Mul(Mul((a / i) + 3, a / i), a / i), (mu[j] - mu[i - 1] + dmod) % dmod)); } ret = Mul(ret, inv6), Inc(ret, dmod - 1); for (i = 1, cnt = 0, x = n; i <= tot && pr[i] <= x / pr[i]; ++i) if (x % pr[i] == 0) { d[++cnt] = pr[i], ct[cnt] = 0; while (x % pr[i] == 0) x /= pr[i], ++ct[cnt]; } if (x > 1) d[++cnt] = x, ct[cnt] = 1; Dfs(1, 1, 1); if (n % mod) ans = Mul(ans, Pow2(n, dmod - 2)), ans %= mod; else ans = (ans / mod) % mod * Pow1(n / mod, mod - 2) % mod; printf("%lld\n", ans); } int main() { register int i, j; ispr[1] = 1, mu[1] = 1; for (i = 2; i < maxn; ++i) { if (!ispr[i]) pr[++tot] = i, mu[i] = -1; for (j = 1; j <= tot && i * pr[j] < maxn; ++j) { ispr[i * pr[j]] = 1; if (i % pr[j]) mu[i * pr[j]] = -mu[i]; else { mu[i * pr[j]] = 0; break; } } } for (i = 2; i < maxn; ++i) mu[i] += mu[i - 1]; scanf("%d", &test); while (test) Solve(), --test; return 0; }