【jxoi2018】游戏 组合数学
首先令n=r−l+1。
令k表示区间[l,r]中存在多少个数x,使得x不存在小于x且在区间[l,r]中的因数,我们把包含这些数的数集称为S
我们来先想一个O(nk)的min−max容斥做法吧。。。。。
显然这一题我们可以转化为min-max容斥的模型(将这k个数选完期望需要选多少次)
maxS=∑T∈S(−1)|T+1|minT。
令Px=∑T∈S and |T|=xminT。
我们推一推式子就会发现Pi=x!(n−x)!∑i=1n−k+1i(n−ik−i)。
然后我们发现这个式子是O(n2)的,而且非常难以推出。
代码如下(这个代码可能有点假)
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 }
考虑一些简单的方法
我们考虑回题目中的枚举排列。令Fi表示 t(p)=i的排列个数,那么答案显然为∑ni=kFi
不难发现,一种t(p)=i的排列,其前i−1项中必包含有数集S中k−1个数,且第i个数必为数集S中的数。
那么不难求出Fi=k(n−k)!i!(i−k)!
答案即为k(n−k)!∑ni=ki!(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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!