Codeforces 822D My pretty girl Noora(最小素因子的性质)

题目大意:一场选美比赛有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^0f(l)+t^1f(l+1)++t^rlf(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 } 
原文地址:https://www.cnblogs.com/fu3638/p/7115096.html