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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P4619 [SDOI2018]旧试题

發(fā)布時間:2023/12/3 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P4619 [SDOI2018]旧试题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

P4619 [SDOI2018]舊試題

題意:

求個式子:
(∑i=1A∑j=1B∑k=1Cd(i?j?k))mod(109+7)(\sum_{i=1}^{A}\sum_{j=1}^{B}\sum_{k=1}^{C}d(i*j*k))mod(10^9+7)(i=1A?j=1B?k=1C?d(i?j?k))mod(109+7)

題解:

原創(chuàng)博文1k紀(jì)念


很明顯,莫比烏斯反演
馬上更新




三元環(huán)鏈接
此等好題,作為第1000題的紀(jì)念

代碼:

這個題讓我寫,我是真寫不出來,非常適合練練莫比烏斯推導(dǎo)
代碼條例非常清晰,很適合閱讀

#include <bits/stdc++.h> #define ll long long using namespace std; const int N= 1e5 + 7; const int M= 1e6 + 7; const int mod= 1e9 + 7; bool Prime[N]; int tot, P[N >> 3], mu[N]; void get_mu() {mu[1]= 1;for (int i= 2; i <= 1e5; i++) {if (!Prime[i])P[++tot]= i, mu[i]= -1;for (int j= 1; P[j] * i <= 1e5 && j <= tot; j++) {Prime[P[j] * i]= 1;if (i % P[j] == 0) {mu[P[j] * i]= 0;break;}mu[P[j] * i]= -mu[i];}} } vector<int> ve[N]; unordered_map<int, bool> mp[N]; int T, Max, A, B, C, ans, p[N]; int sA[M], sB[M], sC[M], cnt, deg[N]; int gcd(int x, int y) {return x == 0 ? y : gcd(y % x, x); } ll lcm(int x, int y) {return 1ll * x / gcd(x, y) * y; } int ta, tb, tc, sum; void cal(int a, int b, int c)//求后半程三個累加的答案 {sum=(sum+ 1ll * p[a / ta] * p[b / tb] % mod * p[c / tc] % mod)% mod; } void get(int a, int b, int c) {sum= 0;if (a == b && b == c)cal(A, B, C);else if (a == b || b == c || c == a) {cal(A, B, C);cal(C, A, B);cal(B, C, A);}else {//三個點的值都不一樣,完全排列 cal(A, B, C);cal(A, C, B);cal(B, A, C);cal(B, C, A);cal(C, A, B);cal(C, B, A);}//記錄后半程的答案 ans= (ans + (mu[a] * mu[b] * mu[c] * sum % mod + mod) % mod) % mod;//記錄前半程答案 } int vis[N]; void solve() {for (int i= 1; i <= cnt; i++) { int &u= sA[i], &v= sB[i];if (deg[u] < deg[v])swap(u, v);else if (deg[u] == deg[v] && u > v)swap(u, v);ve[u].push_back(i);//存的點的編號,為了方便后面取值 }for (int i= 1; i <= Max; i++) {//跑三元環(huán) for (int j : ve[i])vis[sB[j]]= sC[j];for (int j : ve[i])for (int k : ve[sB[j]])if (vis[sB[k]]) {ta= vis[sB[k]];//分別是三個lcm tb= sC[j];tc= sC[k];get(i, sB[j], sB[k]);//三個點的值 }for (int j : ve[i])vis[sB[j]]= 0;} } void getans(int x) {for (int l= 1, r; l <= x; l= r + 1) {r= (x / (x / l));p[x]= (p[x] + 1ll * (r - l + 1) * (x / l) % mod) % mod;//整除分塊前綴和 } } int main() {scanf("%d", &T);get_mu();for (int i= 1; i <= 1e5; i++)getans(i);while (T--) {scanf("%d%d%d", &A, &B, &C);ans= cnt= 0;Max= max(max(A, B), C);for (int i= Max; i >= 1; i--) {//i枚舉的是三數(shù)的人最大公約數(shù)for (int j= i; j <= Max; j+= i) {if (!mu[j])continue;for (int k= j; 1ll*k*j /i<= 1ll * Max; k+= i) {//k*j/i就是這個兩個數(shù)的lcm,要小于等于Max if (!mu[k])continue;if (!mp[j][k]) { // printf("%d %d %d i=%d\n", j, k, j / i * k,i);++cnt;sA[cnt]= j;sB[cnt]= k;sC[cnt]= 1ll*j*k/ i ;//sC是j和k的最小公倍數(shù) deg[j]++;deg[k]++;mp[j][k]= 1;}}}}solve();for (int i= 1; i <= Max; i++) {ve[i].clear();mp[i].clear();deg[i]= 0;}printf("%d\n", (ans + mod) % mod);}return 0; }

總結(jié)

以上是生活随笔為你收集整理的P4619 [SDOI2018]旧试题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。