【筛法求素数】【推导】【组合数】UVALive - 7642 - Prime Distance

题意:n个格子,m个球,让你把球放入某些格子里,使得所有有球的格子之间的距离(abs(i-j))均为素数 ,让你输出方案数。

只占一个格子或者两个格子显然可行。

占有三个格子的情况下,则必须保证其中两者的间距为2,另两者的间距为一个+2以后仍为素数的素数。这个可以预处理。

占有四个格子的情况下,间距只有一种合法情况 2 3 2。

其他情况都不合法。

确定了占有的格子数,尝试放球保证没有一个格子为空的时候,可以用挡板法。

#include<cstdio>
using namespace std;
typedef long long ll;
const ll MOD=1000000007ll;
int T;
ll n,m,ans,in2,in6;
bool notprime[100005];
int primes[100005],pr,prime2[100005],p2;
ll Quick_Pow(ll a,ll p){
    if(p==0ll){
        return 1ll;
    }
    ll res=Quick_Pow(a,p>>1);
    res=res*res%MOD;
    if((p&1ll)==1ll){
        res=a%MOD*res%MOD;
    }
    return res;
}
int main(){
    //freopen("j.in","r",stdin);
    in2=Quick_Pow(2ll,MOD-2ll);
    in6=Quick_Pow(6ll,MOD-2ll);
    int zu=0;
    notprime[1]=1;
    for(int i=2;i<=100000;++i) if(!notprime[i]){
        primes[++pr]=i;
        for(ll j=(ll)i*(ll)i;j<=100000ll;j+=(ll)i){
            notprime[j]=1;
        }
    }
    for(int i=1;i<=pr;++i){
        if(!notprime[primes[i]+2]){
            prime2[++p2]=primes[i];
        }
    }
    scanf("%d",&T);
    for(;T;--T){
        printf("Case %d: ",++zu);
        scanf("%lld%lld",&n,&m);
        ans=(ll)n;
        if(m>1)for(int i=1;i<=pr && n-primes[i]>0;++i){
            ans=(ans+(ll)(n-primes[i])*(ll)(m-1)%MOD)%MOD;
        }
        if(m>2)for(int i=1;i<=p2 && n-prime2[i]-2>0;++i){
            ans=(ans+(ll)(n-prime2[i]-2)*(ll)(m-1)%MOD*(ll)(m-2)%MOD*in2%MOD*2ll%MOD)%MOD;
        }
        if(n>7 && m>3){
            ans=(ans+(ll)(n-7)*(ll)(m-1)%MOD*(ll)(m-2)%MOD*(ll)(m-3)%MOD*in6%MOD)%MOD;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2017-10-28 17:35  AutSky_JadeK  阅读(300)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト