2142: 礼物

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 1450  Solved: 593
[Submit][Status][Discuss]

Description

一年一度的圣诞节快要来到了。每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物。不同的人物在小E心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多。小E从商店中购买了n件礼物,打算送给m个人,其中送给第i个人礼物数量为wi。请你帮忙计算出送礼物的方案数(两个方案被认为是不同的,当且仅当存在某个人在这两种方案中收到的礼物不同)。由于方案数可能会很大,你只需要输出模P后的结果。

Input

输入的第一行包含一个正整数P,表示模;第二行包含两个整整数n和m,分别表示小E从商店购买的礼物数和接受礼物的人数;以下m行每行仅包含一个正整数wi,表示小E要送给第i个人的礼物数量。

Output

若不存在可行方案,则输出“Impossible”,否则输出一个整数,表示模P后的方案数。

Sample Input

100 4 2 1 2

Sample Output

12

【样例说明】
下面是对样例1的说明。
以“/”分割,“/”前后分别表示送给第一个人和第二个人的礼物编号。12种方案详情如下:
1/23 1/24 1/34
2/13 2/14 2/34
3/12 3/14 3/24
4/12 4/13 4/23
【数据规模和约定】
设P=p1^c1 * p2^c2 * p3^c3 * … *pt ^ ct,pi为质数。
对于100%的数据,1≤n≤109,1≤m≤5,1≤pi^ci≤10^5。

HINT

Source

Solution

根据题目大意可以列出式子C(n,sum)*C(sum, w[1])*C(sum-w[1], w[2])··········

如果p是质数的话,显然就是Lucas的裸题。

但现在p不是质数了,要怎么办呢?把p分解成一个个pi^ci,这样的话就保证了两两互质,CRT求解。

那怎么算C(x,y)%(pi^ci)呢?把C(x,y)转化成x!、y!和(x-y)!。

由于需要求逆元,而n!不一定与pi^ci互质,我们就需要把n!分解为k*(pi^x),其中,k与pi互质。

对于当前的n!,我们发现可以把它整理为一些模(pi^ci)下的循环串乘上(pi^(n/pi))再乘上(n/pi)!

举个栗子,17!%(3^2) = (1*2*4*5*7*8*10*11*13*14*16*17)*(3^5)*(1*2*3*4*5)

很显然,栗子最后的那部分就是5!%3这个显然可以递归下去。

对于最前的那部分,我们可以发现,它是由一些循环节(模3^2下)组成的,且均不含有质因数3。

仔细分析,就是[1,3^2]中与质因数3互质的数。求出循环节之后就可以直接用快速幂完成。

对于中间的部分,我们收集起来,算组合数的时候统一再做一次快速幂。

本题主要的问题是处理好逆元的问题,把n!分解成k*(pi^x),含pi的部分单独算,k与pi^ci互质,可以直接求解逆元。

Code

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm> using namespace std; #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define fi first
#define se second
#define mp make_pair
typedef long long LL;
typedef pair<LL, LL> pa;
const int maxn = 1e5;
LL p, a[];
LL prime[maxn+], p_cnt;
bool isNotPrime[maxn+];
LL p_num[], p_mod[], p_sum[], cnt; void prepare()
{
REP(i, , maxn)
{
if (!isNotPrime[i]) prime[++p_cnt] = i;
REP(j, , p_cnt)
{
if (i*prime[j] > maxn) break ;
isNotPrime[i*prime[j]] = ;
if (i%prime[j] == ) break ;
}
}
LL temp = p;
REP(i, , p_cnt)
{
if (prime[i] > temp || temp == ) break ;
if (temp%prime[i] == )
{
p_num[++cnt] = prime[i], p_mod[cnt] = , p_sum[cnt] = ;
while (temp%prime[i] == )
p_mod[cnt] *= prime[i], p_sum[cnt] ++, temp /= prime[i];
}
}
} LL power(LL x, LL y, LL MOD)
{
LL ret = ;
while (y > )
{
if (y&) ret = (ret*x)%MOD;
x = (x*x)%MOD;
y >>= ;
}
return ret;
} pa calc(int k, LL num)
{
if (num == ) return mp(, );
LL x = num/p_num[k], y = num/p_mod[k];
LL ans = ;
if (y)
{
LL t_num = ;
REP(i, , p_mod[k]-)
if (i%p_num[k] != ) t_num = (t_num*i)%p_mod[k];
ans = power(t_num, y, p_mod[k]);
}
if (num%p_mod[k] != )
{
REP(i, , num%p_mod[k])
if (i%p_num[k] != ) ans = (ans*i)%p_mod[k];
}
pa temp = calc(k, x);
return mp(temp.fi+x, temp.se*ans%p_mod[k]);
} LL ex_gcd(LL aa, LL bb, LL &x, LL &y)
{
if (bb == )
{
x = , y = ;
return aa;
}
LL ret = ex_gcd(bb, aa%bb, x, y);
LL temp = x;
x = y, y = temp-(aa/bb)*y;
return ret;
} LL inv(LL k, LL MOD)
{
LL x, y;
ex_gcd(k, MOD, x, y);
x = (x%MOD+MOD)%MOD;
return x;
} LL CRT()
{
LL ret = ;
REP(i, , cnt)
{
LL Mi = p/p_mod[i];
ret = (ret+((Mi*inv(Mi, p_mod[i]))%p*a[i])%p)%p;
}
ret = (ret%p+p)%p;
return ret;
} LL work(LL x, LL y)
{
REP(i, , cnt)
{
pa t1 = calc(i, x), t2 = calc(i, y), t3 = calc(i, x-y);
a[i] = power(p_num[i], t1.fi-t2.fi-t3.fi, p_mod[i]);
a[i] = (((a[i]*t1.se)%p_mod[i]*inv(t2.se, p_mod[i]))%p_mod[i]*inv(t3.se, p_mod[i]))%p_mod[i];
}
return CRT();
} int main()
{
// freopen("a.in", "r", stdin);
// freopen("a.out", "w", stdout);
LL n, m, w[], sum = ;
scanf("%lld %lld %lld", &p, &n, &m);
prepare();
REP(i, , m) scanf("%lld", &w[i]), sum += w[i];
if (sum > n) { puts("Impossible"); return ; }
LL ans = work(n, sum);
REP(i, , m)
ans = (ans*work(sum, w[i]))%p, sum -= w[i];//, printf("%lld\n", ans);
ans = (ans+p)%p;
printf("%lld\n", ans);
return ;
}

 

BZOJ 2142 礼物 组合数学 CRT 中国剩余定理的更多相关文章

  1. NOI 2018 屠龙勇士 (拓展中国剩余定理excrt+拓展欧几里得exgcd)

    题目大意:略 真是一波三折的一道国赛题,先学了中国剩余定理,勉强看懂了模板然后写的这道题 把取出的宝剑攻击力设为T,可得Ti*x=ai(mod pi),这显然是ax=c(mod b)的形式 这部分用e ...

  2. gcd,扩展欧几里得,中国剩余定理

    1.gcd: int gcd(int a,int b){ ?a:gcd(b,a%b); } 2.中国剩余定理: 题目:学生A依次给n个整数a[],学生B相应给n个正整数m[]且两两互素,老师提出问题: ...

  3. 【bzoj3782】上学路线 dp+容斥原理+Lucas定理+中国剩余定理

    题目描述 小C所在的城市的道路构成了一个方形网格,它的西南角为(0,0),东北角为(N,M).小C家住在西南角,学校在东北角.现在有T个路口进行施工,小C不能通过这些路口.小C喜欢走最短的路径到达目的 ...

  4. acm数论之旅--中国剩余定理

    ACM数论之旅9---中国剩余定理(CRT)(壮哉我大中华╰(*°▽°*)╯)   中国剩余定理,又名孙子定理o(*≧▽≦)ツ 能求解什么问题呢? 问题: 一堆物品 3个3个分剩2个 5个5个分剩3个 ...

  5. RSA遇上中国剩余定理

    1.Introduction 最近读论文刚好用到了这个,之前只是有耳闻,没有仔细研究过,这里就好好捋一下,会逐步完善 不过貌似CRT(中国剩余定理)的实现更容易被攻击 2. RSA: Overview ...

  6. 卢卡斯定理&&中国剩余定理

    卢卡斯定理(模数较小,且是质数) 式子C(m,n)=C(m/p,n/p)*C(m%p,n%p)%p 至于证明(我也不会QAQ,只要记住公式也该就好了). 同时卢卡斯定理一般用于组合数取模上 1.首先当 ...

  7. 《孙子算经》之"物不知数"题:中国剩余定理

    1.<孙子算经>之"物不知数"题 今有物不知其数,三三数之剩二,五五数之剩七,七七数之剩二,问物几何? 2.中国剩余定理 定义: 设 a,b,m 都是整数.  如果 m ...

  8. POJ 1006 中国剩余定理

    #include <cstdio> int main() { // freopen("in.txt","r",stdin); ; while(sca ...

  9. [TCO 2012 Round 3A Level3] CowsMooing (数论,中国剩余定理,同余方程)

    题目:http://community.topcoder.com/stat?c=problem_statement&pm=12083 这道题还是挺耐想的(至少对我来说是这样).开始时我只会60 ...

随机推荐

  1. RESTful Web 服务:教程

    RESTful Web 服务:教程   随着 REST 成为大多数 Web 和 Mobile 应用的默认选择,势必要对它的基本原理有所了解. 在它提出十多年后的今天,REST 已经成为最重要的 Web ...

  2. 006_Mac下sublime text 的“package control”安装,sublimepackage

    Mac下sublime text 的“package control”安装,sublimepackage 小伙伴们好,我根据昨晚的经历写一个小总结:关于“Mac下sublime text 的“pack ...

  3. vue引入elementUI 报错

    在main.js里面引入import 'element-ui/lib/theme-default/index.css'中报错,无法启动项目,这是把package.json里面的webpack改成 1 ...

  4. poj1095

    题意:给出n,要求输出第n个二叉树,二叉树编号规则如下图所示: 分析:g[i]表示有i个节点的二叉树,有多少种.f[i][j]表示有i个节点,且左子树有j个节点的树有多少种. sumg[i]表示g数组 ...

  5. dragstart drag dragend dragenter dragover dragleave drop

    dragstart drag dragend dragenter dragover dragleave drop   前端框架层出不穷,网页上的效果越来越绚丽,制作绚丽的效果的成本越来越低,其中有种拖 ...

  6. 洛谷P2016战略游戏

    传送门啦 战略游戏这个题和保安站岗很像,这个题更简单,这个题求的是士兵人数,而保安站岗需要求最优价值. 定义状态$ f[u][0/1] $ 表示 $ u $ 这个节点不放/放士兵 根据题意,如果当前节 ...

  7. MyBatis3.4.0以上的分页插件错误:Could not find method on interface org.apache.ibatis.executor.statement.StatementHandler named prepare. Cause: java.lang.NoSuchMethodException: org.apache.ibatis.executor.stateme

    错误: Could not find method on interface org.apache.ibatis.executor.statement.StatementHandler named p ...

  8. 数据库中INFORMATION_SCHEMA的说明及使用

    第一个查询看看库里有多少个表,表名等select * from INFORMATION_SCHEMA.TABLES information_schema这张数据表保存了MySQL服务器所有数据库的信息 ...

  9. 减小VirtualBox虚拟硬盘文件的大小

    虚拟机使用久了就会发现虚拟硬盘越来越大,但是进入虚拟机里的系统用命令看了下,实际占用的空间远没有虚拟硬盘大小那么大,这个让人很不爽,而且在分享虚拟机镜像的时候也很不方便.VirtualBox似乎没有提 ...

  10. MFC+WinPcap编写一个嗅探器之三(WinPcap)

    介绍程序模块前,这一节再复习一下WinPcap WinPcap开发一个嗅探器的主要步骤如下: (1)获取嗅探设备 WinPcap提供了pcap_findalldevs_ex() 函数来实现这个功能: ...