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^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 } 
时间: 2024-08-08 13:52:09

Codeforces 822D My pretty girl Noora(数论)的相关文章

codeforces 446C DZY Loves Fibonacci Numbers 数论+线段树成段更新

DZY Loves Fibonacci Numbers Time Limit:4000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-14) Description In mathematical terms, the sequence Fn of Fibonacci numbers is defi

Codeforces 396B On Sum of Fractions 数论

题目链接:Codeforces 396B On Sum of Fractions 题解来自:http://blog.csdn.net/keshuai19940722/article/details/20076297 题目大意:给出一个n,ans = ∑(2≤i≤n)1/(v(i)*u(i)), v(i)为不大于i的最大素数,u(i)为大于i的最小素数, 求ans,输出以分式形式. 解题思路:一开始看到这道题1e9,暴力是不可能了,没什么思路,后来在纸上列了几项,突然想到高中时候求等差数列时候用到

Codeforces Round #425 (Div. 2) Problem C (Codeforces 832C) Strange Radiation - 二分答案 - 数论

n people are standing on a coordinate axis in points with positive integer coordinates strictly less than 106. For each person we know in which direction (left or right) he is facing, and his maximum speed. You can put a bomb in some point with non-n

codeforces 402D D. Upgrading Array(dp+数论)

题目链接: codeforces 402D 题目大意: 给出一个数列,可以进行一种操作将某一个前缀除去他们的gcd,有一个函数f(x),f(1) = 0 , f(x) = f(x/p)+1,f(x) = f(x/p)-1(p是坏素数)问 ∑i≤nf(a[i]) 的最大值 题目分析: 首先根据那个递推式我们知道结果就是每个数的f(x)就是它的质因数当中的好素数的个数减去坏素数的个数. 然后我们知道如果某个gcd中好素数的个数小于坏素数的个数,那么我们把它除掉一定可以得到更好的结果,那么如果从最后一

Codeforces 483B Friends and Presents(二分+数论)

题目链接:Codeforces 483B Friends and Presents 题目大意:要将1~v直间的数分配到两个集合中,第一个集合需要cnt1个数,第二个需要cnt2个数,第一个集合中的数 不能是x的倍数,同理第二个集合不能是y的倍数,两集合元素不能相同,问说v最小可以为多少. 解题思路:这题比第三题要难,想了有一会.二分答案,v,然后判断. 判断的时候只要分别判断集合一,二个数是否满足,但是因为有些数可以被分到两个集合,所以要判断总的可分配个数 是否满足大于cnt1+cnt2,计算总

[Codeforces 757E] Bash Plays with Functions (数论)

题目链接: http://codeforces.com/contest/757/problem/E?csrf_token=f6c272cce871728ac1c239c34006ae90 题目: 题解: $f_0(n) = 2^{n的不同质因子的个数}$ $ f_r(n) = \sum_{d|n}f_{r-1}(d)$ $f_0$是积性函数 , $f_r = f_0 * Id^r (1) $也是积性函数 原文地址:https://www.cnblogs.com/xxzh/p/9532304.ht

Codeforces - 346A - Alice and Bob - 简单数论

http://codeforces.com/problemset/problem/346/A 观察了一下,猜测和他们的最大公因数有关,除以最大公因数前后结果是不会变的. 那么怎么证明一定是有n轮呢?我猜就是因为现在至少有几个是互质的,所以总是可以构造出1?具体怎么证明呢?还是看看别人的思路吧-- 首先最终停止的状态一定是一个等差数列,这个是毫无疑问的.设首项为d,那么肯定停止于d,2d,3d,...,n,那么很显然d就是他们的最大公因数啊--对哦?! #include<bits/stdc++.h

Codeforces 360D Levko and Sets (数论好题)

题意:有一个长度为n的数组a和一个长度为m的数组b,一个素数p.有n个集合,初始都只有一个1.现在,对(i从1到n)第i个集合执行以下操作: 对所有集合中的元素c,把c * (a[i] ^ b[j]) mod p 加入集合(j从1到m), 直到集合的元素不再增加为止. 问最后这n个集合的并有多少个元素? n到1e4, m到1e5, p到1e9. 思路(官方题解)这题运用了很多数论的知识,不对数论有一定了解比较难做出这道题. 涉及的知识:原根,阶,欧拉定理,贝祖定理. 首先我们知道,x ^ y m

Codeforces 546D Soldier and Number Game(数论)

类似筛素数的方法--求出前缀和.然后直接O(1)回答即可. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define rep(i,a,b) for(int i(a); i <= (b); ++i) 6 7 const int N = 10000000 + 10; 8 9 int num[N]; 10 bool p[N]; 11 int T, n, m; 12 13 int main(){ 14 15 memset(p,