Harvest of Apples (HDU多校第四场 B) (HDU 6333 ) 莫队 + 组合数 + 逆元
题意大致是有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 ) 莫队 + 组合数 + 逆元的更多相关文章
- 2018 HDU多校第四场赛后补题
2018 HDU多校第四场赛后补题 自己学校出的毒瘤场..吃枣药丸 hdu中的题号是6332 - 6343. K. Expression in Memories 题意: 判断一个简化版的算术表达式是否 ...
- HDU 多校第四场题解
对于 D 题的原题意,出题人和验题人赛前都没有发现标算存在的问题,导致了许多选手的疑惑和时间的浪费,在此表示真诚的歉意! 预计难度分布: Easy - DJKL, Medium - ABCEG, Ha ...
- HDU 6333 莫队+组合数
Problem B. Harvest of Apples Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K ...
- 2014多校第四场1006 || HDU 4902 Nice boat (线段树 区间更新)
题目链接 题意 : 给你n个初值,然后进行两种操作,第一种操作是将(L,R)这一区间上所有的数变成x,第二种操作是将(L,R)这一区间上所有大于x的数a[i]变成gcd(x,a[i]).输出最后n个数 ...
- 2014多校第四场1005 || HDU 4901 The Romantic Hero (DP)
题目链接 题意 :给你一个数列,让你从中挑选一些数组成集合S,挑另外一些数组成集合T,要求是S中的每一个数在原序列中的下标要小于T中每一个数在原序列中下标.S中所有数按位异或后的值要与T中所有的数按位 ...
- hdu多校第四场 1003 (hdu6616) Divide the Stones 机智题
题意: 给你重量分别为1到n的n个石头,让你分成重量相等,数量也相等的k组,保证k是n的约数.问你能不能分配,如果能,输出具体的分配方案. 题解: 首先,如果1到n之和不能整除k,那么一定不能如题意分 ...
- hdu多校第四场 1007 (hdu6620) Just an Old Puzzle 逆序对
题意: 给你一个数字拼图,问你数字拼图能否能复原成原来的样子. 题解: 数字拼图的性质是,逆序数奇偶相同时,可以互相转化,逆序数奇偶不同,不能互相转化. 因此统计逆序对即可. #include< ...
- hdu多校第四场1001 (hdu6614) AND Minimum Spanning Tree 签到
题意: 一个完全图,某两点边权为这两点编号之按位与,求最小生成树,输出字典序最小的. 题解: 如果点数不为$2^n-1$,则每一点均可找到一点,两点之间边权为0,只需找到该点二进制下其最左边的0是第几 ...
- 2018 HDU多校第三场赛后补题
2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube ...
随机推荐
- 1分钟k线图能反映什么?(转)
对于投资者特别是短线操作者来讲,应该重视1分钟K线图,但是并不是所有的股票都能通过1分钟K线图看出名堂来,比如一些小盘股,盘子较轻,很容易上蹿下跳.仅用1分钟K线图分析其上证指数,很难研判大盘当日的高 ...
- CSIC_716_20191111【函数对象、名称空间、作用域、global 和nonlocal】
函数名是可以被引用,传递的是函数的内存地址.函数名赋值给变量后,只需要在变量后加上括号即可调用函数. 名称空间 内置名称空间:在python解释器中提前定义完的名字 全局名称空间:if.while.f ...
- php多维数组排序方案。按照姓名 首字符 等排序
//定义一个学生数组 $students = array( 256=>array('name'=>'jon','grade'=>98.5), 2=>arra ...
- drop database出现1010
> drop database glc; ERROR (HY000): Error dropping database (can't rmdir './glc/', errno: 17) Fri ...
- 校园商铺-2Logback配置与使用-2Logback配置
logback配置文件加载顺序 logback:程序在运行的时候,会按照一定的顺序去加载logbook相关的配置文件. 如果我们在配置里面制定了logbackConfigurationFile这个属性 ...
- 廖雪峰Java16函数式编程-2Stream-6reduce
1. 聚合方法 Stream.reduce()是一个Stream的聚合方法:把一个Stream的所有元素聚合成一个结果 例如: Stream.of(1, 2, 3, 4, 5).count(); // ...
- 8种形式的Android Dialog使用举例
在Android开发中,我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框,在我们使用Android的过程中,我归纳了一 ...
- Installer - Eclipse配置Data Source Explorer
一.配置Oracle数据库连接 1.打开配置窗口 在[window]菜单中的[show windows]选择[other],在弹出的窗口中选择[Data Source Explorer]进行数据数据库 ...
- Android Drawable 详解(教你画画!)
参考 1.Android中的Drawable基础与自定义Drawable 2.android中的drawable资源 3.Android开发之Shape详细解读 Drawable分类 No xml标签 ...
- hibernate annotation 之 注解声明
@Entity 将一个 POJO 类注解成一个实体 bean ( 持久化 POJO 类 ) @Table 为实体 bean 映射指定具体的表,如果该注解没有被声明,系统将使用默认值 ( 即实体 bea ...