• 牛客练习赛 小D的Lemon 解题报告


    小D的Lemon

    题意

    已知

    [g(x)=left{egin{matrix} 1&,x=1\ sum_{i=1}^qk_i&,otherwise end{matrix} ight. ]

    [prod_{i=1}^nprod_{j=1}^mg(gcd(i,j)) ]

    说明

    多组数据,(Tle 1000,n,mle 250000)


    式子太久没推都推不好了...

    [egin{aligned} prod_{i=1}^nprod_{j=1}^m g(gcd(i,j))=&prod_{d=1}^ng(d)^{sumlimits_{i=1}^nsumlimits_{j=1}^m[gcd(i,j)=d]}\ =&prod_{d=1}^{min(n,m)}g(d)^{sumlimits_{k=1}^{min(lfloorfrac{n}{d} floor, floorfrac{m}{d} floor)}mu(k)lfloorfrac{n}{dk} floorlfloorfrac{m}{dk} floor}\ =&prod_{T=1}^{min(n,m)}(prod_{d|T}g(d)^{mu(frac{T}{d})})^{lfloorfrac{n}{T} floorlfloorfrac{m}{T} floor} end{aligned} ]

    把括号里面的预处理出来就可以了

    复杂度(O(nsqrt n+Tlog nsqrt n))或者(O(nln n+Tlog nsqrt n))


    Code:

    #include <cstdio>
    const int N=250000;
    const int mod=1e9+7;
    int min(int x,int y){return x<y?x:y;}
    inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    #define mul(x,y) (1ll*(x)*(y)%mod)
    int qp(int d,int k){int f=1;while(k){if(k&1)f=mul(f,d);d=mul(d,d),k>>=1;}return f;}
    int g[N+10],mu[N+10],ispri[N+10],pri[N+10],yuu[N+10],yuuinv[N+10],cnt,inv[21];
    int cal(int x,int y)
    {
    	if(y==1) return x;
    	if(y==0) return 1;
    	return inv[x];
    }
    void init()
    {
    	g[1]=mu[1]=1;
    	for(int i=2;i<=N;i++)
    	{
    		if(!ispri[i])
    		{
    			pri[++cnt]=i;
    			g[i]=1;
    			mu[i]=-1;
    		}
    		for(int j=1;j<=cnt&&pri[j]*i<=N;j++)
    		{
    			int x=pri[j]*i;
    			ispri[x]=1;
    			g[x]=g[i]+1;
    			if(i%pri[j]) mu[x]=-mu[i];
    			else break;
    		}
    	}
    	for(int i=1;i<=20;i++) inv[i]=qp(i,mod-2);
    	yuu[0]=yuuinv[0]=1;
    	for(int j,i=1;i<=N;i++)
    	{
    		int bee=1;
    		for(j=1;j*j<i;j++)
    		{
    			if(i%j) continue;
    			bee=mul(bee,cal(g[j],mu[i/j]));
    			bee=mul(bee,cal(g[i/j],mu[j]));
    		}
    		if(j*j==i) bee=mul(bee,cal(g[j],mu[i/j]));
    		yuu[i]=mul(yuu[i-1],bee);
    	}
    	for(int i=1;i<=N;i++) yuuinv[i]=qp(yuu[i],mod-2);
    }
    int main()
    {
    	init();
    	int T,n,m;
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d%d",&n,&m);
    		int ans=1;
    		for(int l=1,r;l<=min(n,m);l=r+1)
    		{
    			r=min(n/(n/l),m/(m/l));
    			ans=mul(ans,qp(mul(yuu[r],yuuinv[l-1]),1ll*(n/l)*(m/l)%(mod-1)));
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    2019.2.16

  • 相关阅读:
    Math.floor,Math.ceil,Math.rint,Math.round用法
    double类型转换为int类型四舍五入工具类
    精度更高的double类型计算工具类(借助BigDecimal类型)
    Java中float和double转换的问题
    Java对数
    iPhone内存溢出——黑白苹果
    VBS猜数游戏
    HTML_1
    MySQL学习
    Python进制转换
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10386737.html
Copyright © 2020-2023  润新知