函数 贪心
【题目描述】
【输入格式】
三个整数。
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; }
PEACE