JZOJ 5701. 【gdoi2018 day2】第一题 谈笑风生(magic)
Description
Input
Output
Sample Input
5 7 66
4 3 2 1 5
1 2
1 5
2 3
2 4
2 5
3 4
3 5
Sample Output
6 64
Data Constraint
Hint
Solution
這題的瓶頸就在于如何快速地求出邊權(quán)的大小。
求出來后就可以直接二分答案+spfa了。
考慮莫比烏斯反演(設(shè)邊兩端的權(quán)值分別為 n,m?(n<m)n,m(n<m)):
設(shè)函數(shù)
f(d)=∑i=1n∑j=1m(i+j)[gcd(i,j)=1]f(d)=∑i=1n∑j=1m(i+j)[gcd(i,j)=1]顯然我們要求的答案即為 f[1]f[1] ,但是直接求 ff 并不容易,于是我們再設(shè)函數(shù)g(d)=∑i=1n∑j=1m(i+j)[d|gcd(i,j)]g(d)=∑i=1n∑j=1m(i+j)[d|gcd(i,j)]
那么則有:
g(d)=∑i=1?nd?f(di)g(d)=∑i=1?nd?f(di)反演得:
f(d)=∑i=1?nd?g(di)?μ(i)f(d)=∑i=1?nd?g(di)?μ(i)于是 gg 可以直接求,用兩次等差數(shù)列求和來表示:(首項(xiàng)+末項(xiàng))*項(xiàng)數(shù)/2。
第一次等差數(shù)列變換:g(d)=∑i=1?nd?di??md?+(d+?md??d)??md?2g(d)=∑i=1?nd?di??md?+(d+?md??d)??md?2
(原理就是 ii 的貢獻(xiàn)和 jj 的貢獻(xiàn)分開算,jj 的貢獻(xiàn)滿足等差數(shù)列的形式)
第二次等差數(shù)列變換:g(d)=(d+?md??d)??nd???md?2+(d??md?+d??nd???md?)??nd?2g(d)=(d+?md??d)??nd???md?2+(d??md?+d??nd???md?)??nd?2
g(d)=d?(2+?nd?+?md?)??nd???md?2g(d)=d?(2+?nd?+?md?)??nd???md?2原理也是一樣,帶 ii 的項(xiàng)滿足等差數(shù)列的形式,而后面的常數(shù)項(xiàng)先提出來。
于是我們可以表示出 f(d)f(d) ,即:
f(d)=∑i=1?nd?g(di)?μ(i)f(d)=∑i=1?nd?g(di)?μ(i)f(d)=∑i=1?nd?di?(2+?ndi?+?mdi?)??ndi???mdi?2?μ(i)f(d)=∑i=1?nd?di?(2+?ndi?+?mdi?)??ndi???mdi?2?μ(i)那我們要求的 f(1)?(d=1)f(1)(d=1) 就能長成這樣:
f(1)==∑i=1ni?(2+?ni?+?mi?)??ni???mi?2?μ(i)f(1)==∑i=1ni?(2+?ni?+?mi?)??ni???mi?2?μ(i)對于 ?ni??ni? ,?mi??mi? 這樣的形式我們都可以分塊解決(值最多只有 O(n??√+m??√)O(n+m) 種)。
同時(shí)維護(hù)一個(gè)前綴和 pre[i]pre[i] 即可:
pre[i]=∑j=1ij?μ(j)pre[i]=∑j=1ij?μ(j)這樣分塊計(jì)算時(shí)就可以把值相同的一段段算了。
于是我們就快速地求出了邊權(quán),剩下的二分+spfa就很簡單了。
總時(shí)間復(fù)雜度 O(m?(Ax???√+Ay???√)+km?log?T)O(m?(Ax+Ay)+km?logT) 。
Code
#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> using namespace std; typedef long long LL; const int N=1e4+5; int n,m,tot; LL T,ans; int first[N],nex[N<<2],en[N<<2]; LL w[N<<2]; int a[N],q[N*10],f[N],miu[N],pre[N]; bool bz[N]; LL dis[N]; inline int read() {int X=0,w=0; char ch=0;while(!isdigit(ch)) w|=ch=='-',ch=getchar();while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline int min(int x,int y) {return x<y?x:y; } inline void insert(int x,int y,LL z) {nex[++tot]=first[x];first[x]=tot;en[tot]=y;w[tot]=z; } inline bool check(LL val) {memset(dis,60,sizeof(dis));memset(bz,false,sizeof(bz));int l=dis[1]=0,r=q[1]=1;while(l<r){if(dis[n]<=T) return true;int x=q[++l];bz[x]=false;for(int i=first[x];i;i=nex[i]){LL vv=w[i]-val<0?0:w[i]-val;if(dis[x]+vv<dis[en[i]]){dis[en[i]]=dis[x]+vv;if(!bz[en[i]]) bz[q[++r]=en[i]]=true;}}}return dis[n]<=T; } inline bool getans(LL val) {memset(dis,60,sizeof(dis));memset(bz,false,sizeof(bz));int l=dis[1]=0,r=q[1]=1;while(l<r){int x=q[++l];bz[x]=false;for(int i=first[x];i;i=nex[i]){LL vv=w[i]-val<0?0:w[i]-val;if(dis[x]+vv<dis[en[i]]){dis[en[i]]=dis[x]+vv;if(!bz[en[i]]) bz[q[++r]=en[i]]=true;}}} } int main() {freopen("magic.in","r",stdin);freopen("magic.out","w",stdout);n=read(),m=read();scanf("%lld",&T);for(int i=1;i<=n;i++) a[i]=read();miu[1]=pre[1]=1;for(int i=2;i<N;i++){if(!bz[i]){f[++f[0]]=i;miu[i]=-1;}for(int j=1;j<=f[0] && i*f[j]<N;j++){bz[i*f[j]]=true;if(i%f[j]==0){miu[i*f[j]]=0;break;}miu[i*f[j]]=-miu[i];}pre[i]=pre[i-1]+miu[i]*i;}for(int i=1;i<=m;i++){int x=read(),y=read();int vx=a[x],vy=a[y];if(vx>vy) swap(vx,vy);LL sum=0;for(int j=1,p;j<=vx;j=p+1){p=min(vx/(vx/j),vy/(vy/j));int xx=vx/p,yy=vy/p;sum+=(LL)xx*yy*(xx+yy+2)/2*(pre[p]-pre[j-1]);}insert(x,y,sum);insert(y,x,sum);}LL l=0,r=1e18;while(l<=r){LL mid=l+r>>1;if(check(mid)){ans=mid;r=mid-1;}else l=mid+1;}getans(ans);printf("%lld %lld",ans,dis[n]);return 0; } 與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的JZOJ 5701. 【gdoi2018 day2】第一题 谈笑风生(magic)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 5702. 【gdoi2018
- 下一篇: JZOJ 4161. 于神之怒