题目大意:一场选美比赛有N个人,可以分成N/x,每组x人。每组的比较次数为x(x-1)/2,f[N]为最后决出冠军所需的比较次数,可以通过改变x的值使f[N]改变。求 t0·f(l) + t1·f(l + 1) + … + tr - l·f(r). 题目给出t,l,r(1 ≤ t < 109 + 7, 2 ≤ l ≤ r ≤ 5·106)。由于数字很大,所以需要取模1e9 + 7
思路:令f[i]表示人数为i时需要比较的次数
1、当人数是素数的时候,显然只能分成一组,直接选出冠军,比较次数就是(n*(n-1)/2)
2、当人不是素数的时候,若先分成每x个人一组,(对每一组来说还需要不断进行更小的分组来选出冠军,所以可以将每一组重新看成一个问题,这里不能让每一组的比较次数简单的等于(x*(x-1)/2))那么每组需要比较的次数就是f[x],选出n/x个人后,即这阶段结束之后还需要对选出的n/x个人进行再次分组选择,对这n/x个人需要比较的次数就是f[n/x],f[n]=f[x]*(n/x)+f[n/x]
3、当每组人数,即x为n的最小的质因数的时候,比较次数最少(暂时解释不清,有待补充)
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
using namespace std;
typedef long long ll;
const ll mod =(1e9+7);
#define inf 0x3f3f3f3f
int t,l,r;
const int maxn=5e6+10;
const int maxm=1e6+10;
ll prime[maxn],vis[maxn],f[maxn],tot,factor[maxn];
void init()//求出素数
{
int i,j,k,m;
tot=0;
m=(int)sqrt(maxn+0.5);
memset(vis,0,sizeof(vis));
for(i=2;i<=m;i++)
{
if(!vis[i])
{
for(j=i*i;j<maxn;j+=i)
vis[j]=1;
}
}
for(i=2;i<maxn;i++)if(!vis[i])prime[tot++]=i;
}
void find()//求出最小质因数
{
for(int i=2;i<=maxn;i++)
{
if(!vis[i]) factor[i]=i;
else
{
for(int j=0;j<tot;j++)
{
if(i%prime[j]==0)
{
factor[i]=prime[j];
break;
}
}
}
}
}
int main()
{
init();
find();
scanf("%d%d%d",&t,&l,&r);
f[1]=0; f[2]=1;f[3]=3;
for(int i=4;i<=r;i++)
{
if(!vis[i])
{
f[i]=((ll)i*(i-1)/2)%mod;
}
else
{
int x=factor[i];
f[i]=(((i/x)*f[x])%mod+f[i/x])%mod;
}
}
ll sum=0;
ll tmp=1;
for(int i=l;i<=r;i++)
{
sum=(sum+tmp*f[i])%mod;
tmp=(tmp*t)%mod;
}
printf("%lld\n",sum);
return 0;
}