• BZOJ 2186 SDOI2008 沙拉公主的困惑 数论


    题目大意:给定询问组数T和取模数P,每次询问给定两个整数n和m,求1~(n!)的数中与m!互质的数个个数模P (m<=n)

    首先T<=1W,暴力肯定过不去,我们须要预处理一些东西

    首先我们知道,若x与y互质,则x+y与y也互质,x+2y与y也互质。。。

    换到这道题上来说,若一个数x与m!互质,那么x+(m!)也一定与m!互质,(x+m!*2)也一定与m!互质。。。

    因为n!一定是m!的倍数,于是我们每存在到一个x<=m!与m!互质,我们就一定能找到(n!)/(m!)个与m!互质的数

    而m!以内与m!互质的数的数量恰好是φ(m!)

    于是我们要得到的数恰好就是φ(m!)*(n!)/(m!) %p

    当中m!的全部质因数恰好就是m以内全部的质数 于是φ(m!)=(m!)*∏(pi-1)/pi (pi<=m)

    于是最后我们的结果就是n!*∏(pi-1)/pi

    质数预处理出来,n!预处理出来,pi的逆元预处理出来,∏(pi-1)/pi就能够预处理出来,都是线性的

    至于pi的逆元 有一个比較快的线性求法(详见 http://blog.csdn.net/whyorwhnt/article/details/19169035 )

    我的代码最后交上去超时了1.5秒AC。。。并且我还不是最慢的,wulala大神比我还要慢200+MS。。。

    #include<bitset>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define M 10000001
    using namespace std;
    typedef long long ll;
    bool not_prime[M+100];
    ll prime[500500],ans[M+100],fac[M+100],rev[M+100];
    int n,m,p,T,tot;
    void Linear_Shaker()
    {
    	ll i,j;
    	for(i=2;i<=M;i++)
    	{
    		if(!not_prime[i])
    			prime[++tot]=i;
    		for(j=1;j<=tot&&prime[j]*i<=M;j++)
    		{
    			not_prime[prime[j]*i]=1;
    			if(i%prime[j]==0)
    				break;
    		}
    	}
    	fac[1]=1;
    	for(i=2;i<=M;i++)
    		fac[i]=fac[i-1]*i%p;
    	rev[1]=1;
    	for(i=2;i<=M&&i<p;i++)
    		rev[i]=(p-p/i)*rev[p%i]%p;
    	ans[1]=1;
    	for(i=2;i<=M;i++)
    	{
    		if(!not_prime[i])
    			ans[i]=ans[i-1]*(i-1)%p*rev[i%p]%p;
    		else
    			ans[i]=ans[i-1];
    	}
    }
    int main()
    {
    	scanf("%d%d",&T,&p);
    	Linear_Shaker();
    	for(int i=1;i<=T;++i)
    	{
    		scanf("%d%d",&n,&m);
    		printf("%d
    ",fac[n]*ans[m]%p);
    	}
    }
    


  • 相关阅读:
    SQL数据库优化总结
    数据库设计的三大范式
    springmvc的原理与流程
    flask实现文件下载功能
    python操作excel向同一sheet循环追加数据
    python操作es处理超过10000条数据报错查询不到
    CentOS 安装rz和sz命令 lrzsz实现文件传输
    centOS安装ElasticSearch
    gunicorn启动fastapi命令
    如何获取协程的返回值
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4090351.html
Copyright © 2020-2023  润新知