HDU 6169(数论+DP)

来源:互联网 发布:数据库安全审计系统 编辑:程序博客网 时间:2024/06/14 17:02



Problem Description

Senior Pan had just failed in his math exam, and he can only prepare to make up for it. So he began a daily task with Master Dong, Dong will give a simple math problem to poor Pan everyday.

But it is still sometimes too hard for Senior Pan, so he has to ask you for help.
Dong will give Pan three integers L,R,K every time, consider all the positive integers in the interval [L,R], you’re required to calculate the sum of such integers in the interval that their smallest divisor (other than 1) is K.

 

Input
The first line contains one integer T, represents the number of Test Cases.
Then T lines, each contains three integers L,R,K(1≤L≤R≤10^11,2≤K≤10^11)
 

Output
For every Test Case, output one integer: the answer mod 10^9+7


 
Sample Input
21 20 52 6 3
 

Sample Output
Case #1: 5Case #2: 3
简单想一下就可以发现这个题其实是叫你 令 S<K 求 ( L-1 )/K , ( R )/K 范围内不是 S 的倍数的数(注:所有的 S )
并且 K 必须是素数。
理论上来讲是要容斥一下,但其实是用DP哒(具体有什么联系我不知道请dalao们指出)
这个样子:dp[i][j]=dp[i][j-1]-dp[i/prime[j]][j-1]*prime[j];( i 是求 1 到 i 的和,j 是第 j 个素数,所以 dp[i][j] 表示小于等于 i 的数中不是 j 以及 j 以前的素数的倍数的所有数之和) 
因为数太大DP数组存不下就小范围打表大范围DFS吧代码:
#include <cstdlib>#include <cstring>#include <cstdio>#include <iostream>#include <cmath>using namespace std;typedef long long LL;const LL MOD=1e9+7;const LL A=2e4+7,B=1e3+7,MAXN=340000+7;LL prime[MAXN],total;bool isprime[MAXN];void make(){    LL m=MAXN-3;    memset(isprime,true,sizeof(isprime));    isprime[0]=isprime[1]=false;    total=0;    for(int i=2;i<=m;i++)    {        if(isprime[i])prime[++total]=i;        for(int j=1;j<=total&&prime[j]*i<=m;j++)        {            isprime[i*prime[j]]=false;            if(i%prime[j]==0)break;        }    }}LL dp[A][B];LL L,R,K;LL dfs(LL n,LL m){    if(m==0)    {        LL x=n,y=n+1;        if(x&1)y/=2;        else x/=2;        x%=MOD;y%=MOD;        return x*y%MOD;    }    if(n<=1)return n;    if(prime[m]>=n&&m>0)return 1;    if(n<A&&m<B)return dp[n][m];    LL a=dfs(n,m-1),b=dfs(n/prime[m],m-1)*prime[m];    b=(b%MOD+MOD)%MOD;    a=a-b;    a=(a%MOD+MOD)%MOD;    return a;}int main(){    make();    memset(dp,0,sizeof(dp));    for(LL i=1;i<A;i++)    {        dp[i][0]=i*(i+1)/2;        for(LL j=1;j<B;j++)        {            dp[i][j]=dp[i][j-1]-dp[i/prime[j]][j-1]*prime[j];            dp[i][j]=(dp[i][j]%MOD+MOD)%MOD;        }    }    int T,cas=0;    scanf("%d",&T);    while(T--)    {        scanf("%lld%lld%lld",&L,&R,&K);        printf("Case #%d: ",++cas);        int flag=0;        for(LL i=2;i*i<=K;i++)        {            if(K%i==0)flag=1;            if(flag)break;        }        if(flag)        {            puts("0");            continue;        }        LL z=sqrt(R);        if(K>z)        {            if(L<=K&&K<=R)            {                printf("%lld\n",K%MOD);            }            else puts("0");            continue;        }        int t=0;        R/=K;L=(L-1)/K;        for(int i=1;i<=total;i++)        {            if(prime[i]>=K)break;            t++;        }        LL a=dfs(R,t)*K,b=dfs(L,t)*K;        LL ans=a-b;        ans=(ans%MOD+MOD)%MOD;        printf("%lld\n",ans);    }    return 0;}/*22222222222 777777777 9222222222 777777777 33333333333 9999999999 2Case #1: 0Case #2: 268518521*/



博主在写这个的时候很困,所以有什么错误请谅解
本人蒟蒻,如有错误,还望指正



原创粉丝点击