【解決手段】JXOI2018タイトルゲーム(組み合わせの数)
効果の対象に
以下のために\([L、R] \ ) の数で、あなたは操作が数と、すべての倍数を削除することである必要があります。すべての数字を削除するように依頼する手順と、すべてのプログラムの数のを。あなたはポイントが削除された「削除」することができます:ここでの質問の意味を簡素化することであるため、記載されていない一つのことがあります。それでもまでやっていきたい場合、あなたは、すべての数字を削除した場合でも、\(R-L + 1 \ ) 倍異なる削除。これは、プログラムに含まれます。
まだ明確ではない、あなたはカンカン元のタイトルに行くことができるかもしれません...
実際に私はこの問題に対する解決策について書きたかった思考の方法であるためであります...
検討([L、R] \ \ ) 彼の側に多数の各偶数倍数。これは、トポロジマップを形成することができます。ポイントを削除するには、\(X \)効果は、すべてのトポロジができている(X \)\削除された点に到達します。次いで度にあるすべての必要十分条件のマップ全体を削除\(0 \)ポイントが削除されます。その後の程度と考えて\(0 \)数であるの。側面の一部にも数は彼の間隔ファクタの存在に起因する、それは数が原因で境界よりも彼の最もについて、いくつかの入力されているではありません\(Lの\) 。最小係数=最小の素因数-どのようにスクリーニング数の最も数を考慮することについて彼は要因の最小数を削除することができ、一定値未満です。品質要因は、すべての直接線形ふるいの数に最小化することができます。
実際には、上の段落は明らかにオフ3に要約することができますが、私はこのアイデアについて記録したい、それが非常に書かれていますぶらぶら歩きますクリア。
実際にプログラムの数順列を削除することを検討してください。注\(N = R-L + 1、M = \) がゼロに等しい点の数に。
列挙削除する必要が\(iは\)ステップを、さらに言わ\(m個\)最初の桁\が(私は\)だけ全ビット現れます。次に、フロントため\(iはGEのM \ \)の位置を、第一帝国の最初の\(Iは\)ビットが\(メニュー\ mは1 \)は、その後、その他の構成は、単にある\((M-1 )!\)が、バックフィルからの位置設定値がアップしていることをいくつかの欠点があります\(A_ {NM} ^ { IM} \) 、その後、その他の構成は、乱数れる\((Ni)が!\) 。
最终答案:
\ [\ sum_ {M \ルI \ルn}はI(M-1){mは\ 1を選択} {NM \ IMを選択}(IM)(NI)!!\]
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std; typedef long long ll;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(c<48||c>57)f|=c==45,c=getchar();
while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=1e7+5;
const int mod=1e9+7;
int usd[maxn],Min[maxn];
int jc[maxn],inv[maxn];
vector<int> ve;
inline int ksm(const int&base,const int&p){
int ret=1;
for(int t=p,b=base%mod;t;t>>=1,b=1ll*b*b%mod)
if(t&1) ret=1ll*ret*b%mod;
return ret;
}
inline void pre(const int&n){
jc[0]=inv[0]=1;
for(register int t=1;t<=n;++t) jc[t]=1ll*jc[t-1]*t%mod;
inv[n]=ksm(jc[n],mod-2);
for(register int t=n-1;t;--t) inv[t]=1ll*inv[t+1]*(t+1)%mod;
Min[1]=10; usd[1]=1;
for(register int t=2;t<=n;++t){
if(!usd[t]) ve.push_back(t),Min[t]=t;
for(register auto i:ve){
if(1ll*i*t>n) break;
usd[i*t]=1;
Min[i*t]=min(Min[t],i);
if(t%i==0) break;
}
}
}
inline int c(const int&n,const int&m){
if(n<m)return 0;
return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}
int l,r,m,n;
int main(){
l=qr(); r=qr();
n=r-l+1;
pre(r+3);
for(register int t=l;t<=r;++t) if(t<1ll*l*Min[t]) ++m;
int ans=0;
for(register int t=m,ret;t<=n;++t){
ret=1ll*t%mod*m%mod*c(n-m,t-m)%mod*jc[t-1]%mod*jc[n-t]%mod;
ans=(ans+ret)%mod;
}
printf("%d\n",ans);
return 0;
}