• 【jxoi2018】游戏 组合数学


    首先令$n=r-l+1$。

    令$k$表示区间$[l,r]$中存在多少个数$x$,使得$x$不存在小于$x$且在区间$[l,r]$中的因数,我们把包含这些数的数集称为$S$

    我们来先想一个$O(nk)$的$min-max$容斥做法吧。。。。。

    显然这一题我们可以转化为min-max容斥的模型(将这k个数选完期望需要选多少次)

    $max_{S}=sum_{T∈S}(-1)^{|T+1|}min_{T}$。

    令$P_x=sum_{T∈S and |T|=x} min_{T}$。

    我们推一推式子就会发现$P_i=x!(n-x)!sum_{i=1}{n-k+1}iinom{n-i}{k-i}$。

    然后我们发现这个式子是$O(n^2)$的,而且非常难以推出。

    代码如下(这个代码可能有点假)

     1 #include<bits/stdc++.h>
     2 #define L long long
     3 #define MOD 1000000007
     4 #define M 10000005
     5 using namespace std;
     6 
     7 L pow_mod(L x,L k){L ans=1; for(;k;k>>=1,x=x*x%MOD) if(k&1) ans=ans*x%MOD; return ans;}
     8 L fac[M]={0},invfac[M]={0};
     9 L C(int n,int m){return fac[n]*invfac[m]%MOD*invfac[n-m]%MOD;}
    10 
    11 int vis[M]={0}; 
    12 int n,k=0;
    13 
    14 L p[M]={0};
    15 
    16 int main(){
    17     fac[0]=1; for(int i=1;i<M;i++) fac[i]=fac[i-1]*i%MOD;
    18     invfac[M-1]=pow_mod(fac[M-1],MOD-2);
    19     for(int i=M-2;~i;i--) invfac[i]=invfac[i+1]*(i+1)%MOD;
    20     
    21     int l,r; cin>>l>>r; n=r-l+1;
    22     for(int i=l;i<=r;i++){
    23         if(vis[i]) continue;
    24         k++;
    25         for(int j=i;j<=r;j+=i) vis[j]=1;
    26     }
    27     
    28     for(int x=1;x<=k;x++){
    29         L now=0;
    30         for(int i=1;i<=n-x+1;i++){
    31             L s=i;
    32             for(int j=1;j<x;j++) s=s*(n-i-j+1)%MOD;
    33             now=(now+s)%MOD;
    34         }
    35         p[x]=now*x%MOD*fac[n-x]%MOD;
    36     }
    37     L ans=0;
    38     for(L x=1,zf=1;x<=k;x++,zf=-zf){
    39         ans=(ans+zf*p[x]*C(k,x)%MOD+MOD)%MOD;
    40     }
    41     cout<<ans<<endl;
    42 }

    考虑一些简单的方法

    我们考虑回题目中的枚举排列。令$F_i$表示 $t(p)=i$的排列个数,那么答案显然为$sum_{i=k}^{n}F_i$

    不难发现,一种$t(p)=i$的排列,其前$i-1$项中必包含有数集$S$中$k-1$个数,且第i个数必为数集$S$中的数。

    那么不难求出$F_i=k(n-k)!dfrac{i!}{(i-k)!}$

    答案即为$k(n-k)!sum_{i=k}^{n} dfrac{i!}{(i-k)!}$

    随便求一求就好了

     1 #include<bits/stdc++.h>
     2 #define L long long
     3 #define MOD 1000000007
     4 #define M 10000005
     5 using namespace std;
     6 
     7 L pow_mod(L x,L k){L ans=1; for(;k;k>>=1,x=x*x%MOD) if(k&1) ans=ans*x%MOD; return ans;}
     8 L fac[M]={0},invfac[M]={0};
     9 L C(int n,int m){return fac[n]*invfac[m]%MOD*invfac[n-m]%MOD;}
    10 
    11 int vis[M]={0}; 
    12 int n,k=0;
    13 
    14 L p[M]={0};
    15 
    16 int main(){
    17     fac[0]=1; for(int i=1;i<M;i++) fac[i]=fac[i-1]*i%MOD;
    18     invfac[M-1]=pow_mod(fac[M-1],MOD-2);
    19     for(int i=M-2;~i;i--) invfac[i]=invfac[i+1]*(i+1)%MOD;
    20     
    21     int l,r; cin>>l>>r; n=r-l+1;
    22     for(int i=l;i<=r;i++){
    23         if(vis[i]) continue;
    24         k++;
    25         for(int j=i;j<=r;j+=i) vis[j]=1;
    26     }
    27     L ans=k*fac[n-k]%MOD,sum=0;
    28     for(int i=k;i<=n;i++)
    29     sum=(sum+fac[i]*invfac[i-k])%MOD;
    30     cout<<ans*sum%MOD<<endl;
    31 }
  • 相关阅读:
    linux 删除某种规则命名的文件
    adb shell 出现 error :
    android 开发,多个线程共用一个handler
    android 开发上传图片遇到返回 FileNotFoundException
    mysql 的存储过程调试软件
    输入adb shell 时 提示error: more than one device and emulator
    高德开发 android 出现 key 鉴权失败
    android 中设置HttpURLConnection 超时并判断是否超时
    LINQ to SQL语句(3)之Count/Sum/Min/Max/Avg
    C# 如何判断数据是否为 NaN
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10346635.html
Copyright © 2020-2023  润新知