zoukankan      html  css  js  c++  java
  • 51nod 1584 加权约数和 约数和函数小trick 莫比乌斯反演

    LINK:加权约数和

    我曾经一度认为莫比乌斯反演都是板子题.

    做过这道题我认输了 不是什么东西都是板子.

    一个trick 设(s(x))为x的约数和函数.

    (s(icdot j)=sum_{x|i}sum_{y|j}[(x,y)==1]xcdot frac{j}{y})

    证明的话可以自己意会 赶时间.

    然后 这道题唯一特别的是转换完后 直接莽推根号做法是行不通的 同时也过不去.

    不如先考虑求 (f_i=sum_{j=1}^i s(icdot j))

    然后带入上面的那个trick 莫比乌斯反演一波 发现什么都得不到.

    此时 配合上面trick的转换是 (f_i=sum_{j=1}^isum_{x|j,x|i}mu(x)sum_{u|i,x|u}sum_{v|j,x|v}ufrac{j}{v})

    绝妙或者是套路的转换为 (f_i=sum_{j=1}^isum_{x|j,x|i}mu(x)s(xcdot s(frac{i}{x}))s(frac{j}{x}))

    下面颠倒求和即可.

    然后就可以做了 复杂度 (nlnn+T)

    code
    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<ctime>
    #include<cctype>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000000000000ll
    #define inf 100000000000000000ll
    #define ldb long double
    #define pb push_back
    #define put_(x) printf("%d ",x);
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define gi(x) scanf("%lf",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define vep(p,n,i) for(RE int i=p;i<n;++i)
    #define pii pair<int,int>
    #define mk make_pair
    #define RE register
    #define P 1000000007ll
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define uint unsigned long long
    #define ui unsigned
    #define EPS 1e-10
    #define sq sqrt
    #define S second
    #define F first
    #define mod 1000000007
    #define max(x,y) ((x)<(y)?y:x)
    using namespace std;
    char *fs,*ft,buf[1<<15];
    inline char gc()
    {
    	return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
    	RE int x=0,f=1;RE char ch=gc();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    	return x*f;
    }
    const int MAXN=1000010;
    int n,T,top;
    int v[MAXN],p[MAXN],d[MAXN],sum[MAXN],D[MAXN],w[MAXN],f[MAXN],in[MAXN],mu[MAXN];
    inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    inline int mul(int x,int y){return (ll)x*y%mod;}
    inline int mus(int x,int y){return x-y<0?x-y+mod:x-y;}
    inline int ksm(int b,int p)
    {
    	int cnt=1;
    	while(p)
    	{
    		if(p&1)cnt=mul(cnt,b);
    		b=mul(b,b);p=p>>1;
    	}
    	return cnt;
    }
    inline void prepare()
    {
    	sum[1]=mu[1]=in[1]=d[1]=D[1]=1;
    	rep(2,n,i)
    	{
    		in[i]=mul(in[mod%i],(mod-mod/i));
    		if(!v[i])
    		{
    			v[i]=p[++top]=i;mu[i]=-1;
    			w[i]=p[top];d[i]=i+1;
    			D[i]=add(1+i,(ll)i*i%mod);
    		}
    		sum[i]=add(d[i],sum[i-1]);
    		rep(1,top,j)
    		{
    			if(p[j]>n/i)break;
    			int ww=p[j]*i;
    			v[ww]=p[j];
    			if(v[i]==p[j])
    			{
    				w[ww]=w[i]*p[j];
    				if(w[ww]==ww)
    				{
    					d[ww]=add(d[i],ww);
    					D[ww]=add(D[i],add((ll)ww*ww%mod,(ll)i*i%mod*p[j]%mod));
    				}
    				else 
    				{
    					d[ww]=mul(d[i/w[i]],d[w[ww]]);
    					D[ww]=mul(D[i/w[i]],D[w[ww]]);
    				}
    				break;
    			}
    			w[ww]=p[j];d[ww]=mul(d[i],d[p[j]]);
    			D[ww]=mul(D[i],D[p[j]]);
    			mu[ww]=-mu[i];
    		}
    	}
    	/*rep(1,1000,i)
    	{
    		if(D[i]!=d[i*i])
    		{
    			cout<<"ww"<<endl;
    			cout<<i<<endl;
    			return;
    		}
    	}*/
    	rep(1,n,i)
    	{
    		if(mu[i])
    		{
    			for(int j=i;j<=n;j+=i)
    			f[j]=(f[j]+mu[i]*(ll)i*d[j/i]%mod*sum[j/i])%mod;
    		}
    		f[i]=((mul(f[i],2*i)-mul(i,D[i]))%mod+mod)%mod;
    		f[i]=add(f[i],f[i-1]);
    	}
    }
    signed main()
    {
    	//freopen("1.in","r",stdin);
    	n=1000000;prepare();
    	get(T);
    	rep(1,T,W)
    	{
    		printf("Case #%d: ",W);	
    		put(f[read()]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    HDU 2639 Bone Collector II (01背包,第k解)
    POJ 2184 Cow Exhibition 奶牛展(01背包,变形)
    hihoCoder #1165 : 益智游戏 (挑战赛11 B题)
    UVA 562 Dividing coins 分硬币(01背包,简单变形)
    POJ Charm Bracelet 挑饰品 (常规01背包)
    hiho一下 第四十四周 博弈游戏·Nim游戏(直接公式解)
    UVA 624 CD(01背包,要记录路径)
    118 Pascal's Triangle 帕斯卡三角形 杨辉三角形
    117 Populating Next Right Pointers in Each Node II 每个节点的右向指针 II
    116 Populating Next Right Pointers in Each Node 每个节点的右向指针
  • 原文地址:https://www.cnblogs.com/chdy/p/13387510.html
Copyright © 2011-2022 走看看