题意大致是有n个苹果,问你最多拿走m个苹果有多少种拿法。题目非常简单,就是求C(n,0)+...+C(n,m)的组合数的和,但是询问足足有1e5个,然后n,m都是1e5的范围,直接暴力的话肯定时间炸到奶奶都不认识了。当时想了好多好多,各种骚操作都想了一遍就是没想到居然是莫队....我用S(n,m)来记录C(n,0)+...+C(n,m)的和作为一个询问的答案

由组合数公式C(n,m) = C(n-1,m-1)+C(n-1,m)可以推的下面的式子

S(n,m) = S(n,m-1) + C(n,m);

S(n,m) = S(n,m+1) - C(n,m+1);

S(n,m) = 2*S(n-1)-C(n,m);

S(n,m) = ( S(n+1, m) + C(n,m) ) / 2;

这样发现居然是一个莫队的基本操作....然而只知道这几点也是不够的,因为组合数计算涉及到除法,所以得求逆元,还是阶乘的逆元,所以得先预处理出1~n的阶乘和它们的逆元,求逆元也是很耗时间的,但是我们可以通过递推一遍把阶乘的逆元求出来

设f(x)为x的逆元
那么 f(n!) = f( (n-)!*n ) = f((n-)!)*f(n);
将f(n)除过来 f(n!)*f(f(n)) = f((n-)!)
因为x的逆元的逆元就是x本身, 因此得到公式f(n!)*n = f((n-1)!),这样我们只要求出最大的阶乘的逆元就可以从大到小推出所有逆元的值

就酱(顺便说一句不知道为啥hdu选c++会TLE或者WA,得用G++编译)

 #include <iostream>
#include <string.h>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <math.h>
#include <string>
#include <algorithm>
#include <functional> #define SIGMA_SIZE 26
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) (x&-x)
#define foe(i, a, b) for(int i=a; i<=b; i++)
#define fo(i, a, b) for(int i=a; i<b; i++)
#define pii pair<int,int>
#pragma warning ( disable : 4996 ) using namespace std;
typedef long long LL;
inline double dMax(double a, double b) { return a>b ? a : b; }
inline double dMin(double a, double b) { return a>b ? b : a; }
inline LL LMax(LL a, LL b) { return a>b ? a : b; }
inline LL LMin(LL a, LL b) { return a>b ? b : a; }
inline LL lgcd(LL a, LL b) { return b == ? a : lgcd(b, a%b); }
inline LL llcm(LL a, LL b) { return a / lgcd(a, b)*b; } //a*b = gcd*lcm
inline int Max(int a, int b) { return a>b ? a : b; }
inline int Min(int a, int b) { return a>b ? b : a; }
inline int gcd(int a, int b) { return b == ? a : gcd(b, a%b); }
inline int lcm(int a, int b) { return a / gcd(a, b)*b; } //a*b = gcd*lcm
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = 1e9+;
const double eps = 1e-;
const int inf = 0x3f3f3f3f;
const int maxk = 3e6 + ;
const int maxn = 1e5+; int n, m, unit;
int belong[maxn];
LL fac[maxn], inv[maxn],invof2;
LL ans[maxn];
struct node {
int lhs, rhs, id;
}pp[maxn]; bool cmp(const node& a, const node& b)
{
if (belong[a.lhs] == belong[b.lhs])
return (belong[a.lhs]&) ? a.rhs<b.rhs : a.rhs>b.rhs;
return a.lhs < b.lhs;
} //设f(x)为x的逆元
//f(n!) = f( (n-1)!*n ) = f((n-1)!)*f(n);
//将f(n)除过来 f(n!)*f(f(n)) = f((n-1)!)
//因此可以从最大的n反向推回小的
LL getM( LL a, LL b, LL m)
{
LL ans = , base = a;
while (b)
{
if ( b & )
ans = (ans*base) % m;
base = (base*base) % m;
b >>= ;
}
return ans;
} void init()
{
fac[] = fac[] = ;
inv[] = inv[] = ;
foe(i, , maxn)
fac[i] = fac[i-]*i%mod; inv[maxn-] = getM(fac[maxn-], mod-, mod);
invof2 = getM(, mod-, mod);
for ( int i = maxn-; i >= ; i-- )
inv[i] = (inv[i+]*(i+))%mod;
} LL C(int down, int up)
{
if ( up > down ) return ;
return fac[down]*inv[up]%mod*inv[down-up]%mod;
} int main()
{
init();
int T;
cin >> T;
unit = sqrt(T); foe(i, , T)
{
scanf("%d %d", &n, &m);
pp[i].lhs = n; pp[i].rhs = m;
pp[i].id = i;
belong[i] = i/unit+;
}
sort(pp+, pp++T, cmp); //(l代表n, r代表m)
int l = , r = ;
LL sum = ; for ( int i = ; i <= T; i++ )
{
while (r < pp[i].rhs) {
r++;
sum = (sum + C(l, r))%mod;
} while (r > pp[i].rhs) {
sum = (sum - C(l, r)+mod)%mod;
r--;
} while (l < pp[i].lhs) {
sum = ((LL)*sum - C(l, r)+mod)%mod;
l++;
} while (l > pp[i].lhs) {
l--;
sum = (sum+C(l,r))%mod*invof2%mod;
} ans[pp[i].id] = sum;
} foe(i, , T)
printf("%lld\n", ans[i]);
return ;
}

Harvest of Apples (HDU多校第四场 B) (HDU 6333 ) 莫队 + 组合数 + 逆元的更多相关文章

  1. 2018 HDU多校第四场赛后补题

    2018 HDU多校第四场赛后补题 自己学校出的毒瘤场..吃枣药丸 hdu中的题号是6332 - 6343. K. Expression in Memories 题意: 判断一个简化版的算术表达式是否 ...

  2. HDU 多校第四场题解

    对于 D 题的原题意,出题人和验题人赛前都没有发现标算存在的问题,导致了许多选手的疑惑和时间的浪费,在此表示真诚的歉意! 预计难度分布: Easy - DJKL, Medium - ABCEG, Ha ...

  3. HDU 6333 莫队+组合数

    Problem B. Harvest of Apples Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K ...

  4. 2014多校第四场1006 || HDU 4902 Nice boat (线段树 区间更新)

    题目链接 题意 : 给你n个初值,然后进行两种操作,第一种操作是将(L,R)这一区间上所有的数变成x,第二种操作是将(L,R)这一区间上所有大于x的数a[i]变成gcd(x,a[i]).输出最后n个数 ...

  5. 2014多校第四场1005 || HDU 4901 The Romantic Hero (DP)

    题目链接 题意 :给你一个数列,让你从中挑选一些数组成集合S,挑另外一些数组成集合T,要求是S中的每一个数在原序列中的下标要小于T中每一个数在原序列中下标.S中所有数按位异或后的值要与T中所有的数按位 ...

  6. hdu多校第四场 1003 (hdu6616) Divide the Stones 机智题

    题意: 给你重量分别为1到n的n个石头,让你分成重量相等,数量也相等的k组,保证k是n的约数.问你能不能分配,如果能,输出具体的分配方案. 题解: 首先,如果1到n之和不能整除k,那么一定不能如题意分 ...

  7. hdu多校第四场 1007 (hdu6620) Just an Old Puzzle 逆序对

    题意: 给你一个数字拼图,问你数字拼图能否能复原成原来的样子. 题解: 数字拼图的性质是,逆序数奇偶相同时,可以互相转化,逆序数奇偶不同,不能互相转化. 因此统计逆序对即可. #include< ...

  8. hdu多校第四场1001 (hdu6614) AND Minimum Spanning Tree 签到

    题意: 一个完全图,某两点边权为这两点编号之按位与,求最小生成树,输出字典序最小的. 题解: 如果点数不为$2^n-1$,则每一点均可找到一点,两点之间边权为0,只需找到该点二进制下其最左边的0是第几 ...

  9. 2018 HDU多校第三场赛后补题

    2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube ...

随机推荐

  1. C++ 系列:交换两个数字

    1. 创建中间变量 这是最快也是最简单的办法,例如: #include<stdio.h> int main(){ int a=10; int b=20; int temp; printf( ...

  2. java 数组常见操作

    1.遍历  依次访问数组中的每个元素 public class ArrayDemo04 { public static void main(String[] args) { int[] arr = { ...

  3. python3和python2编码拾遗

    py2编码 tr和unicode str和unicode都是basestring的子类.严格意义上说,str其实是字节串,它是unicode经过编码后的字节组成的序列.对UTF-8编码的str'苑'使 ...

  4. C# GZipStream 压缩 解压

    关于GZipStream压缩解压,网上找了很多资料,完整的不多,要么是针对字符串压缩解压缩的,要么只实现了针对单个文件的压缩解压缩,还有的不支持子文件夹的压缩,实用性都不是很大. 以下整理了压缩解压缩 ...

  5. https://www.cnblogs.com/chinabin1993/p/9848720.html

    转载:https://www.cnblogs.com/chinabin1993/p/9848720.html 这段时间一直在用vue写项目,vuex在项目中也会依葫芦画瓢使用,但是总有一种朦朦胧胧的感 ...

  6. idea的安装与破解

    1.下载 官网:https://www.jetbrains.com/idea/download/#section=windows 百度盘:https://pan.baidu.com/s/16mRNPK ...

  7. 03_mybatis配置文件详解

    1. SqlMapConfig.xml mybatis全局配置文件SqlMapConfig.xml,配置内容如下: *properties(属性) setting(全局配置参数) typeAliase ...

  8. 关于vlfeat做vlad编码问题

    这里是官方文档,可以自己查看 在这里,只是想记录一下,我这几天学习vlfeat 做vlad编码的过程,便于以后整理 网上涉及到vlfeat做vlad编码资料较少,而官网上例子又相对简单,主要是那几个参 ...

  9. <前端>简单实现开心网注册

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. 13-1-return

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...