题目大意:一场选美比赛有N个人,可以分成N/x,每组x人。每组的比较次数为x(x-1)/2,f[N]为最后决出冠军所需的比较次数,可以通过改变x的值使f[N]改变。题目给出t,l,r(1 ≤ t < 109 + 7, 2 ≤ l ≤ r ≤ 5·106)。求 t^0⋅f(l)+t^1⋅f(l+1)+⋯+t^r−l⋅f(r) 的最小值对1e9+7的模。
解题思路:①如果人数为素数,那f[N]=N(N-1)/2;
②如果不是素数,那就找出最小素因子x,分成N/x,每组x人,f[N]=N/x*f[x]+f[N/x]。
关于②,比如6可以分为3个2或者2个3,所需比较数分别是5和7,显然分的组数越多越好。还有关于为什么加上f[N/x],因为是递推的,所以f[N/x]肯定也是最小的,不用担心N/x不是素数还要在进行分组的问题。
代码:
1 #include<iostream> 2 using namespace std; 3 typedef long long ll; 4 const int N=5e6+5; 5 const ll MOD=1e9+7; 6 bool prime[N]; 7 ll p[N]; 8 ll f[N]; 9 int cnt; 10 //素数表 11 void is_prime(){ 12 for(int i=2;i<=N;i++) 13 prime[i]=true; 14 for(int i=2;i*i<=N;i++){ 15 if(prime[i]){ 16 p[cnt++]=i; 17 for(int j=i*i;j<=N;j+=i){ 18 prime[j]=false; 19 } 20 } 21 } 22 } 23 24 int main(){ 25 is_prime(); 26 f[1]=0; 27 for(int i=2;i<N;i++){ 28 //判断是否为素数 29 if(prime[i]){ 30 f[i]=((ll)i*(i-1)/2)%MOD; 31 } 32 else{ 33 //找最小素因子 34 ll factor; 35 for(int j=0;j<cnt;j++){ 36 if(i%p[j]==0){ 37 factor=p[j]; 38 break; 39 } 40 } 41 f[i]=(i/factor*f[factor]+f[i/factor])%MOD; 42 } 43 } 44 ll ans=0; 45 ll t,l,r; 46 cin>>t>>l>>r; 47 for(int i=r;i>=l;i--){ 48 ans=(ans*t)%MOD; 49 ans=(ans+f[i])%MOD; 50 } 51 cout<<ans<<endl; 52 }