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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

hdu4676 ------麦比乌斯反演分块

發布時間:2024/3/12 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu4676 ------麦比乌斯反演分块 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4676


解題思路:總體上這是一個數學題加上離線與分塊處理加速。顯然對于區間內有公約數x的數來說,假設有num[x]個x的倍數,那么答案顯然是sigma(C(num[x],2)*f(x)),根據容斥原理f(x)應該是一個小于x的數并且滿足sigma(f(d)) = x{d|x},因為有x這個約數的數對一定也有d這個約數,其中d|x,所以我在加上C(num[x],2)*f(x)之前就把C(num[d],2)*f(d)加上了,而總共對于x所需累加的次數是x,所以有sigma(f(d)) = x{d|x},而這正是麥比烏斯反演公式,可得f(d)為歐拉函數,http://www.isnowfy.com/mobius-inversion/

? ? ? ?然后每加入一個數我們只要加上num[x]*phi[x]就行了(根據組合公式的性質比較容易看出)。但是直接暴力的話復雜度會超,就是對于查詢區間大幅波動的情況就需要不停的加入點,刪除點,復雜度估計能達到n平方,所以我們采用離線查詢的方式,然后對查詢左端點分段排,在每一段內保證查詢右端點的有序性,這樣就可以大致保持查詢左端點和右端點的有序性。下面上代碼:


#include<cstdio> #include<iostream> #include<vector> #include<cmath> #include<cstring> #include<algorithm> #define N 20005 using namespace std; int phi[N],a[N],num[N],ans[N]; int L,R,ret; vector<int>d[N]; struct node {int l,r,id,s; }seg[N]; void init() {for(int i = 1;i<N;i++)phi[i] = i;for(int i = 2;i<N;i++)if(phi[i] == i)for(int j = i;j<N;j+=i)phi[j] = phi[j]/i*(i-1);for(int i = 1;i<N;i++)for(int j = i;j<N;j+=i)d[j].push_back(i); } void Insert(int x) {for(int i = 0;i<d[x].size();i++){int v = d[x][i];ret+=num[v]*phi[v];num[v]++;} } void Delete(int x) {for(int i = 0;i<d[x].size();i++){int v = d[x][i];num[v]--;ret-=num[v]*phi[v];} } void query(int l,int r) {for(int i = l;i<L;i++)Insert(a[i]);for(int i = L;i<l;i++)Delete(a[i]);for(int i = r+1;i<=R;i++)Delete(a[i]);for(int i = R+1;i<=r;i++)Insert(a[i]); } bool cmp(node x,node y) {if(x.s == y.s)return x.r<y.r;return x.s<y.s; } int main() {int t,y,n,m,i,j,cas = 1;scanf("%d",&t);init();while(t--){scanf("%d",&n);int size = sqrt(1.0*n);memset(num,0,sizeof(num));for(i = 1;i<=n;i++)scanf("%d",&a[i]);scanf("%d",&m);for(i = 1;i<=m;i++){scanf("%d%d",&seg[i].l,&seg[i].r);seg[i].id = i;seg[i].s = seg[i].l/size;}sort(seg+1,seg+m+1,cmp);ret = 0;L = seg[1].l;R = seg[1].r;for(i = L;i<=R;i++)Insert(a[i]);ans[seg[1].id] = ret;for(i = 2;i<=m;i++){query(seg[i].l,seg[i].r);L = seg[i].l;R = seg[i].r;ans[seg[i].id] = ret;}printf("Case #%d:\n",cas++);for(i=1;i<=m;i++)printf("%d\n",ans[i]);}return 0; }

總結

以上是生活随笔為你收集整理的hdu4676 ------麦比乌斯反演分块的全部內容,希望文章能夠幫你解決所遇到的問題。

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