标签:highlight oid 描述 type atom http typedef main 贪心
【输入格式】
三个整数。
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+b−1)/2;
通式为:
F(n)=ab*(ab-1) *x/2;
因为a,b是素数,所以一定都大于等于2
所以b*x*(a²−a+b−1)/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;
}
标签:highlight oid 描述 type atom http typedef main 贪心
原文地址:http://www.cnblogs.com/gshdyjz/p/7672644.html