Codeforces Round #422 (Div. 2) D. My pretty girl Noora [数论][dp]

传送门:http://codeforces.com/contest/822/problem/D

题意:求${t^0}f(l) + {t^1}f(l + 1) + ... + {t^{r - l}}f(r)$ f(x)代表每次把x个人分成人数相等的若干个组进行比赛,每组有一个胜利的情况下,最后淘汰到只剩一个人需要最少进行比赛的次数 例如f(2)=1。

很明显的看出是dp问题 假设f(100)被分为50个2人组答案一定为f(50)+1*50 很容易能观察到每队分配越少人的情况下答案越优。

证明:简单证明的话可以假设每次都分为d个人一组,人数为n 大约需要的总次数大约为logd(n)*d求导后为单调增函数,但是这样证明不是很准确。官方证明是假设d为合数,有d=a*b,可以推导出,所以d为素数时最优,代码如下。

ps:此类可以暴力的题目对拍查错效率很高!

 1 #define _CRT_SECURE_NO_DEPRECATE
 2 #pragma comment(linker, "/STACK:102400000,102400000")
 3 #include<iostream>  
 4 #include<cstdio>  
 5 #include<fstream>  
 6 #include<iomanip>
 7 #include<algorithm>  
 8 #include<cmath>  
 9 #include<deque>  
10 #include<vector>  
11 #include<assert.h>
12 #include<bitset>
13 #include<queue>  
14 #include<string>  
15 #include<cstring>  
16 #include<map>  
17 #include<stack>  
18 #include<set>
19 #include<functional>
20 #define pii pair<int, int>
21 #define mod 1000000007
22 #define mp make_pair
23 #define pi acos(-1)
24 #define eps 0.00000001
25 #define mst(a,i) memset(a,i,sizeof(a))
26 #define all(n) n.begin(),n.end()
27 #define lson(x) ((x<<1))  
28 #define rson(x) ((x<<1)|1) 
29 #define inf 0x3f3f3f3f
30 typedef long long ll;
31 typedef unsigned long long ull;
32 using namespace std;
33 
34 const int maxn = 5e6 + 5;
35 ll dp[maxn];
36 
37 bool visit[maxn];
38 ll prime[maxn];
39 ll sve[maxn];
40 void getprime()
41 {
42     int n = 5000000;
43     memset(visit, false, sizeof(visit));
44     int num = 0;
45     for (ll i = 2; i <= n; ++i)
46     {
47         if (!visit[i]) { prime[++num] = i; sve[i] = i; }
48         for (int j = 1; j <= num && i * prime[j] <= n; j++)
49         {
50             int temp = i*prime[j];
51             visit[temp] = true;
52             if (!sve[temp])sve[temp] = min(i, prime[j]);
53             if (i % prime[j] == 0) break;
54         }
55     }
56 }
57 int main()
58 {
59     ios::sync_with_stdio(false);
60     cin.tie(0); cout.tie(0);
61     int i, j, k, m, n, l, r;
62     ll t;
63     cin >> t >> l >> r;
64     getprime();
65     for (ll i = 2; i <= r; ++i)
66         dp[i] = ((sve[i] * (sve[i] - 1LL)) / 2LL * (i / sve[i]) + dp[i / sve[i]]) % mod;
67     ll sum = 0;
68     ll temp = 1;
69     for (int i = l; i <= r; ++i)
70     {
71         sum = (sum + temp*dp[i]) % mod;
72         temp *= t;
73         temp %= mod;
74     }
75     cout<<sum;
76     return 0;
77 }

 

转载于:https://www.cnblogs.com/Meternal/p/7130523.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值