zoukankan      html  css  js  c++  java
  • 【洛谷P2155】[SDOI2008]沙拉公主的困惑

    题目描述

    大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票。房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的数量。现在,请你帮助沙拉公主解决这个问题,由于可能张数非常大,你只需计算出对R取模后的答案即可。R是一个质数。

    输入输出格式

    输入格式:

    第一行为两个整数T,R。R<=10^9+10,T<=10000,表示该组中测试数据数目,R为模 后面T行,每行一对整数N,M,见题目描述 m<=n

    输出格式:

    共T行,对于每一对N,M,输出1至N!中与M!素质的数的数量对R取模后的值

    输入输出样例

    输入样例#1:
    1 11
    4 2
    输出样例#1:
    1
    
    数据范围:
    对于100%的数据,1 < = N , M < = 10000000

    分析(转载)

    原文地址

    首先,我们来引出一个定理
    如果$a$与$b$互质,那么$b*k+a$也与$b$互质。证明和证明$gcd$的证明类似。
    反过来,我们也可以用$gcd$证明,
    因为$gcd(a,b)=1$,所以$gcd(a\%b,b)=1$
    因为$a\%b=a-k*b$,故$gcd(a-k*b,b)=1$,及$a-k*b$与$b$互质。
    根据这个特性,并且$n>=m$,所以可以将$n!$分成若干段,每段为$m!$,每一段中与$m!$互质的个数都是相等的且等于1到$m!$中与$m!$互质的个数
    我们可以得到式子

    $ans={frac{n!}{m!}*phi(m!)}$

    进一步拆开,我们可以得到 (假设$p$为$m!$的质因数,很容易可以知道,$p$就是所有小于$m$的素数,$r$为质因数个数)

    $ans={frac{n!}{m!}*m!*frac{prod limits_{i=1}^{r}(p_i-1)}{prodlimits_{i=1}^{r}p_i } o ans=n!*frac{prod limits_{i=1}^{r}(p_i-1)}{prodlimits_{i=1}^{r}p_i } }$

    因为$ans$ 要$mod R$,所以我们也要算1到m的逆元,在累乘$prodlimits_{i=1}^{r}p_i$ ,乘的是$p_i$ 的逆元。 有多组询问,我们得先预处理一些数据,累乘的时候要$%R$ 我们令$k[i] = i!$ ,$inv[i]$为$i$的逆元,

    $f1[i]= {prodlimits_{a=1}^{i}(p_a-1)}$
    $f2[i]={prodlimits_{a=1}^{i}p_a}$
    $ans=f1[m]*f2[m]*k[n]$
    先预处理O()答案,对于询问O(1)出解

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn=10000000+1;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int T,p,n,m,tot;
    int fac[maxn],inv[maxn],ans[maxn],prime[maxn];
    bool isp[maxn];
    void prework()
    {
        fac[1]=1; inv[1]=1; ans[1]=1;
        for(int i=2;i<=maxn;i++)
        fac[i]=((ll)fac[i-1]*(i%p))%p;
        for(int i=2;i<=maxn;i++)
        inv[i]=(ll)(p-p/i)*inv[p%i]%p;
        for(int i=2;i<=maxn;i++)
        {
            if(!isp[i]) prime[++tot]=i;
            for(int j=1;j<=tot&&prime[j]*i<=maxn;j++)
            {
                isp[prime[j]*i]=1;
                if(i%prime[j]==0) break;
            }
        }
        for(int i=2;i<=maxn;i++)
        {
            if(!isp[i])
                ans[i]=(ll)ans[i-1]*(i-1)%p*inv[i%p]%p;
            else ans[i]=ans[i-1];
        }
    }
    int main()
    {
        T=read();p=read();
        prework();
        while(T--)
        {
            n=read();m=read();
            printf("%d
    ",(ll)fac[n]*ans[m]%p);
        }
        return 0;
    }
    欢迎转载,转载请注明出处!
  • 相关阅读:
    media Queries实现一个响应式的菜单
    跨域资源共享(CORS)在ASP.NET Web API中是如何实现的?
    Media Formatters媒体格式化器
    Winform系列
    node-webkit入门
    WCF 自承载
    HttpClient的使用-爬虫学习1
    为什么程序员的工作效率跟他们的工资不成比例(转)
    大师们都是怎么撑场面的(转)
    马云关于企业发展的一些看法
  • 原文地址:https://www.cnblogs.com/huihao/p/7501371.html
Copyright © 2011-2022 走看看