码迷,mamicode.com
首页 > 其他好文 > 详细

A 组队参赛

时间:2019-10-10 20:06:25      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:技术   idt   name   limits   long   ioi   sign   tle   scanf   

时间限制 : - MS   空间限制 : - KB 技术图片
评测说明 : 1s,256m
问题描述

一年一度的ioiAKer大赛即将来临,何老板打算让信竞队的同学们组队参赛。信竞队共n名队员,他们的CF积分分别是1、2、3、...... 、n,CF积分体现了选手的能力水平,积分越高,能力越强。
按照赛会方的要求,每个学校只能派两只队伍参赛,分别对应提高组和提高组。为体现不同组别能力的区分度,要求提高组队伍中积分最低的选手必须大于普及组队伍中积分最高的选手。每组队伍的参赛人数不能为0。
何老板想知道,总共有多少种合法的组队方案。结果可能很大,mod m后再输出。

输入格式

一行,两个整数n和m

输出格式

一个整数,表示计算结果

样例输入

3 10

样例输出

5

提示

对于100%的数据:1<=n<=1018 1<=m<=1018

合法的组队方案如下: 提高组 普及组 {3,2} {1} {3} {1,2} {3} {2} {3} {1} {2} {1}

【题目分析】
设i在普及组中,且CF分数最高,显然,∑i=1n {2i - 1 * (2n - i - 1)} % m 就是答案。
即ans = ∑i=1n {2i - 1 * (2n - i - 1)} % m = ∑i=1n {2n - 1 - 2i - 1} % m = {∑i=1n 2n - 1 - ∑i=1n 2i - 1} % m
由等比数列求和公式,可化简为ans = (n * 2n - 1 - (2n - 1)) % m = (n * 2n - 1 - 2n + 1) % m,然后把模运算分配进括号里即可。
但是鉴于n范围过大,我们借用O(1)快速乘,此题解决。
一下安利O(1)快速乘模板:
ll Mul(ll a, ll b, ll c) {
    return (a * b - (ll)((long double)a / c * b) * c + c) % c;
}

 

 
【参考代码】
 1 #include<cstdio>
 2 #define ll unsigned long long
 3 ll n, m, ans, temp;
 4 namespace Ironclad_Programming {
 5     #define R register int
 6     #define For(i, s, n) for (R i = s; i <= n; ++ i)
 7     void ini() {
 8         scanf("%lld%lld", &n, &m);
 9     }
10     ll Mul(ll a, ll b, ll c) {
11         return (a * b - (ll)((long double)a / c * b) * c + c) % c;
12     }
13     ll Montgomery(ll a, ll b, ll c) {
14         ll ans = 1;
15         a %= c;
16         while (b) {
17             if ((b & 1))ans = Mul(ans % c, a % c, c);
18             b >>= 1;
19             a = Mul(a % c, a % c, c);
20         }
21         return ans;
22     }
23     void solve() {
24         temp = Montgomery(2, n - 1, m);
25         ans = Mul(n % m, temp % m, m);
26         temp = Montgomery(2, n, m);
27         ans = (ans - temp + 1 + m) % m; // 千万记得加一次模数,防负数
28         printf("%lld", ans);
29     }
30     void Main() {
31         ini();
32         solve();
33     }
34     #undef R
35     #undef For
36 }
37 int main() {
38     Ironclad_Programming::Main();
39     return 0;
40 }

A 组队参赛

标签:技术   idt   name   limits   long   ioi   sign   tle   scanf   

原文地址:https://www.cnblogs.com/Limbo-To-Heaven/p/11650167.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!