秘密

Description

  为了探索邪恶魔王everlasting的强大力量,l1ll5决定一探究竟!

  l1ll5费尽千辛万苦,终于找到了everlasting的密室,现在,只要解决最后一道难题,他就能得到everlasting的强大力量!

  现在他的面前有x颗石子,他知道,everlasting的神秘力量只在其中的一颗石子中。他想到所有石子中蕴含的能量是不同的,而能量高的石子会将能量低的石子毁灭!每一轮操作中他可以将石子分成相等的几份(注意每轮中所有石子需要先分好组),每份中的石子都会与该份中其他石子进行碰撞,也就是说,如果一份中有s颗石子,就会发生s*(s-1)/2次碰撞!每份的石子碰撞后只会剩下一颗,而everlasting的能量只在其中能量最高的一颗中!也就是说,当分成t份石子得到t个石子后,它们之间还要继续进行下一轮操作,进行划分,碰撞,直到剩下一颗石子。而石子碰撞爆发的能量是很大的,所以l1ll5必须尽可能少的让石子发生碰撞!l1ll5当然顺利的找到了正确的方法,而真相远非如此…

  由于everlasting将自己的能量注入了石子,石子便有了灵力,它向l1ll5提出一个问题:如果石子个数分别是l,l+1,l+2,…,r,那么最优碰撞次数分别是多少,由于everlasting十分喜欢哈希,它把这些值放进一个数组a里,而最后everlasting的神秘力量值为

  c^0*a[l]+c^1*a[l+1]+...+c^(r-l)*a[r] 对1000000007取模的值。如果无法在0.1s内答对,l1ll5将一无所获。l1ll5当然会做啦,但是他想考考你...

Input

输入一行包含三个正整数c,l,r.

Output

输出一行一个正整数,表示everlasting的神秘力量值。

Sample Input

input1:
2 3 4
input2:
3 15 51

Sample Output

output1:
9
output2:
682142060

HINT

【样例说明】

对于三个石子,需要碰撞三次。

对于四个石子,可以分成两组分别碰撞,最后的两个再进行碰撞,需要三次。

答案为3+2*3=9.

【数据规模与约定】

对于10%数据,r<=20。

对于30%数据,r<=2000。

对于50%数据,r<=100000。

对于另20%数据,l=r。

对于所有数据,均匀分布50%数据,c=1。

对于100%数据,1<=c<=1000000007,2<=l<=r<=20000000。

这题其实是一道利用欧拉筛原理进行优化的dp题

dp[i]表示到i个石子最少碰撞几次,则dp[i*prime[j]]=dp[i]+dp[prime[j]]*i 根据数论知识当一个数是素数时其撞击次数只能是n*(n-1)/2,根据贪心思想

当一个数被分成一个大合数组的小素数时撞击次数最少,因此利用欧拉筛进行状态转移

代码:

 1 #include<cstdio>// By Yae Sakura 八重樱 
 2 #include<iostream>
 3 using namespace std;
 4 long long mod=1000000007;
 5 long long dp[20000005];
 6 int prime[6000005];
 7 bool notp[20000005];
 8 int main()
 9 {
10     long long c,l,r;
11     long long s=0;
12     bool a=0;
13     scanf("%lld%lld%lld",&c,&l,&r);
14     long long ans=0,x;
15     int tot=0;
16     for(int i=2;i<=r;i++)
17     {
18         if(!notp[i])
19         {
20             prime[++tot]=i;
21             x=i;
22             dp[i]=(x*(x-1)/2)%mod;
23         }
24         for(int j=1;j<=tot&&i*prime[j]<=r;j++)
25         {
26             notp[i*prime[j]]=1;
27             dp[i*prime[j]]=(1LL*dp[prime[j]]*i+1LL*dp[i])%mod;
28             if(i%prime[j]==0)
29             break;
30         }
31         if(a)
32         s=(s*c)%mod;
33         if(l==i)
34         {
35             a=1;
36             s=1;
37         }
38         if(a)
39         {
40             ans+=s*dp[i];
41             ans%=mod;
42         }    
43     } 
44     printf("%lld",ans);
45 } 
View Code

Over By Yae Sakura

原文地址:https://www.cnblogs.com/mzh2017/p/8149950.html