题意大致是有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. Binary XML file line #23: Error inflating class android.widget.TextView

    分析一波,报错23行TextView的问题,但是检查了xml没有发现23行又TextView相关代码,就不应该继续纠结xml了,代码是通过R文件拿到xml资源的,你就应该怀疑是R文件的问题,R文件编译 ...

  2. NIO 详解

    同步非阻塞 NIO之所以是同步,是因为它的accept read write方法的内核I/O操作都会阻塞当前线程 IO模型 IO NIO 通信 面向流(Stream Oriented) 面向缓冲区(B ...

  3. day12 bash中的if、for

    bash 变量bash 定义:x= 作用:记录状态 规则:字母开头,后面可以接字母.数字.下划线 export args:将变量定义为全局变量 $$[]:括号中可以进行简单的数学整数运算,可以用ech ...

  4. 最大流任务调度——hdu3572二分图建图

    很简单的任务调度模板题 把一个工作完成一天的量当做是边 /* 任务调度问题最大流 因为两个任务之间是没有关系的,两天之间也是没有关系的 所以抽象成二分图 任务i在天数[si,ei]之间都连一条双向边, ...

  5. System.Web.Mvc.HttpOptionsAttribute.cs

    ylbtech-System.Web.Mvc.HttpOptionsAttribute.cs 1.程序集 System.Web.Mvc, Version=5.2.3.0, Culture=neutra ...

  6. JS程序的基本语法

    JS程序的基本语法 JS是区分大小写的.如:Name和name是两个变量 JS中每一条语句,一般以英文下的分号(;)结束.这个分号不是必须的.为了向PHP兼容,最好加上分号. 运算符和变量,以及操作之 ...

  7. transient在java中的作用

    java 的transient关键字的作用是需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中. trans ...

  8. STM32F103 Feature

  9. springboot跨域访问

    写一个WebMvc配置类重写addCorsMappings即可 @Configuration public class MyMvcConfig implements WebMvcConfigurer ...

  10. Django的日常-模型层(1)

    目录 Django的日常-模型层(1) 模型层 django测试环境 ORM查询 Django的日常-模型层(1) 模型层 模型层其实就是我们应用名下的models.py文件,我们在里面写入想要创建的 ...