zoukankan      html  css  js  c++  java
  • [BZOJ4816][SDOI2017]数字表格

    BZOJ
    Luogu
    题意:求

    [prod_{i=1}^{n}prod_{j=1}^{m}f(gcd(i,j)) ]

    其中(f(i))表示斐波那契数列的第(i)项。

    sol

    其实所有莫比乌斯反演的题目都是套路。接下来我们对这句话进行证明。
    首先我们考虑计算每一个不同的(gcd)的贡献

    [ans=prod_{d=1}^{n}f(d)^{sum_{i=1}^{n}sum_{j=1}^{m}[gcd(i,j)==d]} ]

    也就是

    [prod_{d=1}^{n}f(d)^{sum_{i=1}^{n/d}sum_{j=1}^{m/d}[gcd(i,j)==1]} ]

    根据之前的经验套路(都不用再去推了)可得

    [ans=prod_{d=1}^{n}f(d)^{sum_{i=1}^{n/d}mu(i)lfloorfrac {n}{id} floorlfloorfrac {m}{id} floor} ]

    然后你发现这样就是裸的两次数论分块(O(n))
    然后多组数据(O(n))被卡
    然后你就想着怎么优化成开始(O(n))预处理,然后单组数据(O(sqrt n))回答。
    完全就是一模一样的剧情。。。
    我们令(T=id),考虑每一个(lfloorfrac {n}{T} floorlfloorfrac {m}{T} floor)对答案的贡献。

    [ans=prod_{T=1}^{n}(prod_{d|T}f(d)^{mu(frac Td)})^{lfloorfrac {n}{T} floorlfloorfrac {m}{T} floor} ]

    这时候剧情出现了转折。
    你发现这个函数

    [h(T)=prod_{d|T}f(d)^{mu(frac Td)} ]

    它不是一个积性函数!
    我这个傻逼也在这里想了好久
    你看它是枚举因数嘛,枚举因数。。。
    直接(O(sum_{i=1}^{n}frac ni))的复杂度暴搞不就好了吗?
    由于(mu(frac Td))只会有1,-1,0三种取值,而0取值是没有贡献的,所以我们(O(nlog{n}))计算出斐波那契数列及其逆元,然后按照上述方式求出(h(x)),再求其前缀积,然后每组询问就只要一次数论分块了。
    区间积的处理:直接(r)的前缀积乘上(l-1)的前缀积的逆元即可。
    注意指数的取模:是模(varphi(mod))也就是(mod-1)而非(mod)。(然而我看一眼就注意到了hh)

    code

    我是一A的

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int mod = 1e9 + 7;
    const int N = 1e6;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    int fastpow(int a,int b)
    {
    	int res=1;
    	while (b) {if (b&1) res=1ll*res*a%mod;a=1ll*a*a%mod;b>>=1;}
    	return res;
    }
    int mu[N+5],pri[N+5],tot,zhi[N+5],f[N+5],inv[N+5],h[N+5];
    void Mobius()
    {
    	zhi[1]=mu[1]=1;
    	for (int i=2;i<=N;i++)
    	{
    		if (!zhi[i]) pri[++tot]=i,mu[i]=-1;
    		for (int j=1;j<=tot&&i*pri[j]<=N;j++)
    		{
    			zhi[i*pri[j]]=1;
    			if (i%pri[j]) mu[i*pri[j]]=-mu[i];
    			else {mu[i*pri[j]]=0;break;}
    		}
    	}
    	h[0]=1;
    	f[1]=inv[1]=h[1]=1;
    	for (int i=2;i<=N;i++)
    		f[i]=(f[i-1]+f[i-2])%mod,inv[i]=fastpow(f[i],mod-2),h[i]=1;
    	for (int i=1;i<=N;i++)
    		if (mu[i]!=0)
    			for (int j=i;j<=N;j+=i)
    				h[j]=1ll*h[j]*(mu[i]==1?f[j/i]:inv[j/i])%mod;
    	for (int i=2;i<=N;i++)
    		h[i]=1ll*h[i]*h[i-1]%mod;
    }
    int main()
    {
    	Mobius();
    	int T=gi();
    	while (T--)
    	{
    		int n=gi(),m=gi();
    		if (n>m) swap(n,m);
    		int i=1,ans=1;
    		while (i<=n)
    		{
    			int j=min(n/(n/i),m/(m/i));
    			ans=1ll*ans*fastpow(1ll*h[j]*fastpow(h[i-1],mod-2)%mod,1ll*(n/i)*(m/i)%(mod-1))%mod;
    			i=j+1;
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    hdu 1290 献给杭电五十周年校庆的礼物 (DP)
    hdu 3123 GCC (数学)
    hdu 1207 汉诺塔II (DP)
    hdu 1267 下沙的沙子有几粒? (DP)
    hdu 1249 三角形 (DP)
    hdu 2132 An easy problem (递推)
    hdu 2139 Calculate the formula (递推)
    hdu 1284 钱币兑换问题 (DP)
    hdu 4151 The Special Number (DP)
    hdu 1143 Tri Tiling (DP)
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8274365.html
Copyright © 2011-2022 走看看