Bレースシミュレーション問題

トピック:

 

 

 

 

 

 

 

 

分析:

で、k = 2を参照してください。

SBデュティーチふるいファイ

少し寒い、その健康ポイント。

だから、去る55分を書きました。

非常にシンプルなああ2333を見下ろします

GCDを考慮せず、C(N + K-1、K)のプログラム構成の数

GCDを考えるとき、我々はムーを設定する必要があります

ANS =シグマ(I = 1個の... N)MU [I] * F(N / I)

ここで、f(X)= C(X + K-1、K)

そして、式があります。

summu [N] = 1シグマ(D = 2 ... N)summu [N / D]

これは、要求を許可N ^(2/3)summu

Fの場合は、非常に小さなによるKは、それが暴力的とみなすことができます。

しかし、このデータは非常に遅いえっ限度となります。

セグメンテーションプロセスFを考えてみましょう

X + K-1は、以下1E6未満である場合、組み合わせの数は、前処理することができます

また、1E6よりX + K-1少し大きいからです。

だから、2333年は終わりました。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>

#define maxn 1000005
#define INF 0x3f3f3f3f
#define MOD 1000000007

using namespace std;

inline int getint()
{
    int num=0,flag=1;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    return num*flag;
}

int n,K;
int N=1000000;
int pri[maxn],cnt,np[maxn];
int mu[maxn];
long long fac[maxn],inv[maxn];
long long ans;
map<int,long long>M;

inline void init()
{
    mu[1]=1;
    for(int i=2;i<=N;i++)
    {
        if(!np[i])pri[++cnt]=i,mu[i]=-1;
        for(int j=1;j<=cnt&&i*pri[j]<=N;j++)
        {
            np[i*pri[j]]=1;
            if(i%pri[j]==0)break;
            mu[i*pri[j]]=-mu[i];
        }
    }
    for(int i=1;i<=N;i++)mu[i]+=mu[i-1];
    for(int i=1;i<=N;i++)(mu[i]+=MOD)%=MOD;
    fac[0]=fac[1]=inv[0]=inv[1]=1;
    for(int i=2;i<=N;i++)fac[i]=fac[i-1]*i%MOD;
    for(int i=2;i<=N;i++)inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;
    for(int i=2;i<=N;i++)inv[i]=inv[i]*inv[i-1]%MOD;
}

inline long long solve(int x)
{
    if(x<=N)return mu[x];
    if(M.count(x))return M[x];
    long long num=1;
    for(int i=2,j;i<=x;i=j+1)
    {
        j=x/(x/i);
        (num-=(j-i+1)*solve(x/i)%MOD)%=MOD;
    }
    return M[x]=(num+MOD)%MOD;
}

inline long long C(int p,int q)
{return fac[p]*inv[q]%MOD*inv[p-q]%MOD;}

inline long long cal(int x)
{
    if(x+K-1<=N)return C(x+K-1,K);
    long long tmp=1;
    for(int i=1;i<=K;i++)tmp=tmp*((x+K-1)-i+1)%MOD;
    return tmp*inv[K]%MOD;
}

int main()
{
    int T=getint();
    init();
    while(T--)
    {
        M.clear();
        n=getint(),K=getint();
        ans=0;
        for(int i=1,j;i<=n;i=j+1)
        {
            j=n/(n/i);
            (ans+=(solve(j)-solve(i-1)+MOD)*cal(n/i)%MOD)%=MOD;
        }
        printf("%lld\n",ans);
    }
}
View Code

おすすめ

転載: www.cnblogs.com/Darknesses/p/12032207.html