zoukankan      html  css  js  c++  java
  • Bzoj 2186: [Sdoi2008]沙拉公主的困惑 乘法逆元,线性筛,欧拉函数,数论

    2186: [Sdoi2008]沙拉公主的困惑

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 2560  Solved: 857
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

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

    Sample Input

    1 11
    4 2

    Sample Output

    1

    数据范围:
    对于100%的数据,1 < = N , M < = 10000000

    HINT

     

    Source

     题解:
    因为若x和y互质,则x+y,x+2*y,x+3*y …… x+k*y 都与y互质。
    所以若 x<=m! ,且x与m!互质。那么x,x+m!, x+2*m! …… x+k*m! 都与m!互质。
    因为n!为m!的倍数,所以得到与m!互质的x后,则一定有n!/m! 个与m!互质的数(x的倍数)。
    与m!互质且小于等于m!的数的个数就是φ(m!)。
    则ans=φ(m!)*(n!/m!)%R
        =m!*[∏((Pi) - 1)/(Pi)]*(n!/m!)  (Pi<=m)
        =m!*[∏((Pi) - 1)/(Pi)]*(n!/m!)  (Pi<=m)
        =[∏((Pi) - 1)/(Pi)]*n!  (Pi<=m)
    然后预处理出来 质数,∏((Pi) - 1)/(Pi) (Pi<=10000000)  ,n!(1<=n<=10000000)。
    最后O(1)输出即可。
    注意:筛素数要用线性筛。QAQ
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 #define MAXN 10000000
     5 #define MAXP 670010
     6 int jc[MAXN+10],cj[MAXN+10],cc[MAXN+10],tot;
     7 int prime[MAXP],ny[MAXP];
     8 bool vis[MAXN+10];
     9 int read()
    10 {
    11     int s=0,fh=1;char ch=getchar();
    12     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
    13     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
    14     return s*fh;
    15 }
    16 int ksm(LL bb,LL pp,LL kk)
    17 {
    18     LL s=1;
    19     while(pp>0)
    20     {
    21         if(pp%2!=0)s=(LL)(s*bb)%kk;
    22         pp/=2;
    23         bb=(LL)(bb*bb)%kk;
    24     }
    25     return s;
    26 }
    27 void getprime()
    28 {
    29     int i,j;
    30     tot=0;
    31     for(i=2;i<=MAXN;i++)
    32     {
    33         if(vis[i]==false)prime[++tot]=i;
    34         for(j=1;j<=tot&&prime[j]*i<=MAXN;j++)
    35         {
    36             vis[prime[j]*i]=true;
    37             if(i%prime[j]==0)break;
    38         }
    39     }
    40     /*for(i=2;i<=MAXN;i++)
    41     {
    42         if(vis[i]==false)
    43         {
    44             prime[++tot]=i;
    45             for(j=i+i;j<=MAXN;j+=i)vis[j]=true;
    46         }
    47     }*/
    48 }
    49 int main()
    50 {
    51     int T,R,i,N,M;
    52     T=read();R=read();
    53     getprime();
    54     for(i=1;i<=tot;i++)ny[i]=ksm(prime[i],R-2,R);
    55     jc[0]=1;
    56     cj[0]=1;
    57     for(i=1;i<=tot;i++)cc[prime[i]]=(LL)(prime[i]-1)*ny[i]%R;
    58     for(i=1;i<=MAXN;i++)
    59     {
    60         jc[i]=(LL)jc[i-1]*i%R;
    61         if(cc[i]!=0)cj[i]=(LL)cj[i-1]*cc[i]%R;
    62         else cj[i]=cj[i-1];
    63     }
    64     while(T--)
    65     {
    66         N=read();M=read();
    67         printf("%lld
    ",(LL)jc[N]*cj[M]%R);
    68     }
    69     fclose(stdin);
    70     fclose(stdout);
    71     return 0;
    72 }
    View Code
  • 相关阅读:
    [翻译]使用设计模式简化.NET中菜单和Form元素之间的关系
    [AWDwR4]13章出错 protect_against_forgery
    使用存储过程(22)
    建立数据库连接(19)
    对数据库添加数据(21)
    ADO.NET常用对象(18)
    数据展现Repeater控件(25)
    content控件(24)
    对数据库增加数据(21)
    行为存储过程(23)
  • 原文地址:https://www.cnblogs.com/Var123/p/5288927.html
Copyright © 2011-2022 走看看