函数 贪心

【题目描述】

这里写图片描述 
【输入格式】 
  三个整数。 
  1≤t<10^9+7,2≤l≤r≤5*10^6 
【输出格式】 
  一个整数。 
【输入样例】 
2 2 4 
【输出样例】 
19


 

第一眼看到这道题,相信都可以想到F函数是要预处理出来的,但是问题就来了:

怎么得到F函数正确的值呢?

于是我们需要证明:

对于n个人,分解成质因数,按质数个人分为一组(从小到大)结果最大。

证明:

设a,b是n的质因数,a<b

于是我们可以得到:

n=a*b*x;

于是我们又可以得到:

F(n)=(F(a)*b+F(b))*x;

所以当a,b为素数时:

F(n)=b*x*(a²a+b1)/2;

通式为:

F(n)=ab*(ab-1) *x/2;

因为a,b是素数,所以一定都大于等于2

所以b*x*(a²a+b1)/2一定大于等于ab*(ab-1) *x/2;

得证。

于是有了下面的代码(代码不是我打的,但是注释是我打的):

#include<cstdio>
#include<algorithm>

using namespace std;

typedef long long ll;

const ll mods=1e9+7;
const int N=7000000;
int pr[N],lp,n,L,R,t;//pr记录素数,lp是第几个素数 
bool inp[N];//inp记录是不是素数 
ll F[N],ans,tl;

void getpr()
{
    inp[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!inp[i]) 
			{ 
				pr[++lp]=i;//记录素数 
		 		F[i]=(((ll)i*(i-1))>>1)%mods;//F没法分解  
			}
        for(int j=1;(ll)i*pr[j]<=n && j<=lp;j++)//筛法 
        {
            F[pr[j]*i]=(F[pr[j]]*i%mods+F[i])%mods;//下一个素数相乘的结果为循环到的素数结果乘以组数加上 当前素数结果 
            inp[pr[j]*i]=1;//标记非素数  
        }
    }
}

int main()
{
    scanf("%d%d%d",&t,&L,&R);
    n=R; getpr(); tl=1; ans=0;
    for(int i=L;i<=R;i++)
    {
        ll k=F[i];
        ans=(ans+tl*k%mods)%mods;
        tl=tl*t%mods;
    }
    printf("%lld\n",ans);
    return 0;
}

  

posted @ 2017-10-15 16:42  GSHDYJZ  阅读(149)  评论(0编辑  收藏  举报