bzoj 2313 分组 2012-01-15

http://www.zybbs.org/JudgeOnline/problem.php?id=2313

_______________________________________________

对于n要求方案数:

对于n的约数s,即将n个数分为s组,每组有n/s=p个数共有:

ans (p)=(C(p,n)*C(p,n-p)*C(p,n-2p)*...*C(p,p))/(s!)

=(n!*(n-p)!*...*p!)/((p!)^s*(n-p)!*(n-2p)!..1!*s!)

=(n!)/((p!)^s*s!)

种方案

所以总共的方案数就有 total=sigma( ans(si))

题目要求的是  m^total mod (10^9-401)

设prime=10^9-401

prime-1 分解质因数为 di[i]={2,13,5281,7283}

首先需要知道:①费尔马小定理: a^(p-1)=1(mod p)

②  (k-1)! =-1 (mod k)

所以 m^(prime-1)=1 (1 mod prime);

m^ans=m^(ans mod (prime-1)) (mod prime);

所以现在需要求 ans mod (prime-1)

等价于求满足 ans =xi (mod di[i])  (1<=i<=4)  最后将每一个yi 用中国剩余定理合并即求出 x=ans( mod (prime-1))。

最后即可算出每一个x的和即为 total mod (prime-1)

对于 ans=(n!)/((p!)^s*s!) mod di

怎么求 n! mod di 呢?

因为 n!=1*2..(di-1)*di*(di+1)*..*(q*di)*(q*di+1)...*n (mod di)

=((di-1)! mod di)^q*(n-q*di)!*q!*(di)^q ( mod di)

=(-1)^q*(n-q*di)!*q!*di^q ( mod di)

因为(n-q*di)不是特别大(n-q*di)! mod di的值可以预处理出来

所以可以用递归求一个数的阶乘模di的值   求出来的值可以化简为 fac*di^pow

将分数ans 的分子存成  di^pow1*fac1

分母存成  di^pow2*fac2

易证pow1>=pow2 所以当 pow1>pow2时  ans= (fac1/fac2) (mod di);

当 pow1=pow2时  ans= 0 (mod di)

!!!程序合并ans =xi (mod di[i])   用的是求线性模方程组的方法,具体百度

_______________________________________________

  1 Program Stone;
  2 const di:array[1..4]of longint=(2,13,5281,7283);
  3       prime=999999599;
  4 type data=record pow,fac:int64;end;
  5 var i,j,t:longint;
  6     n,m,ans:int64;
  7     aj:array[1..4,0..8000]of int64;
  8     s_up,s_low:array[1..4]of data;
  9     ci:array[1..4]of int64;
 10   function pow(c,x,p:int64):int64;  //求 c^x mod p 的值
 11   var i,k:int64;
 12    begin
 13      pow:=1;
 14      i:=x;
 15      k:=c;
 16      while i>0 do
 17       begin
 18         if i mod 2=1 then pow:=k*pow mod p;
 19         i:=i shr 1;
 20         k:=k*k mod p;
 21       end;
 22    end;
 23
 24   function factorial(p,a:int64):data;  //求 p! mod di[a] 的值,存储成 fac*di[a]^pow
 25   var i,j:int64;
 26       s:data;
 27    begin
 28       i:=p div di[a];j:=p mod di[a];
 29       s.fac:=1;s.pow:=0;
 30       if i>0 then s:=factorial(i,a);
 31       if i mod 2=1 then s.fac:=-s.fac;
 32       s.fac:=(s.fac*aj[a,j]) mod di[a];
 33       s.pow:=(s.pow+i);
 34       factorial:=s;
 35    end;
 36   function exgcd(a,b:int64;var x,y:int64):int64;   //扩展欧几里德
 37
 38   var t:int64;
 39    begin
 40      if b=0 then begin x:=1;y:=0;exit(a);end;
 41      exgcd:=exgcd(b,a mod b,x,y);
 42      t:=x;
 43      x:=y;
 44      y:=t-(a div b)*y;
 45    end;
 46   function work(a,b,n:int64):int64;   //求解  ax=n (mod b)的x 值
 47   var y,g:int64;
 48    begin
 49      g:=exgcd(a,b,work,y);
 50      work:=((work*(n div g) mod (b div g)+(b div g))mod (b div g));  //求出的解应该为最小整数解
 51    end;
 52   function lcm(a,b:int64):int64;   //求最小公倍数
 53   var i,j,k,gcd:int64;
 54    begin
 55      i:=a;j:=b;
 56      while j<>0 do
 57       begin
 58         k:=i;i:=j;j:=k mod j;
 59       end;
 60      lcm:=a*b div i;
 61    end;
 62   Procedure doans(i:int64);   //对于将n分成每组有i 个的方案数
 63   var j:longint;
 64       ai,yi,xi,k:int64;
 65       s:data;
 66    begin
 67      for j:=1 to 4 do    //s_up表示分子,s_low表示分母
 68         begin
 69          s_low[j]:=factorial(n div i,j);
 70          s:=factorial(i,j);
 71          s_low[j].pow:=s_low[j].pow+s.pow*(n div i);
 72          s_low[j].fac:=s_low[j].fac*pow(s.fac,n div i,di[j]);
 73          if s_up[j].pow<>s_low[j].pow then ci[j]:=0
 74                                       else ci[j]:=work(s_low[j].fac,di[j],s_up[j].fac);
 75         end;
 76         ai:=di[1];yi:=ci[1];    //合并ans =xi (mod di[i])
 77         for j:=2 to 4 do
 78         begin
 79           xi:=work(ai,di[j],(ci[j]-yi));
 80           yi:=ai*xi+yi;
 81           ai:=lcm(ai,di[j]);
 82         end;
 83         ans:=(ans+yi)mod (prime-1);
 84    end;
 85   Procedure main;
 86   var i,j:longint;
 87       s:data;
 88    begin
 89       if n>1 then ans:=2 else ans:=1;
 90       for i:=1 to 4 do
 91         s_up[i]:=factorial(n,i);
 92       for i:=2 to round(sqrt(n)) do    //枚举n的约数
 93        if n mod i=0 then
 94          begin
 95            doans(i);
 96            if n div i<>i then doans(n div i);
 97          end;
 98    end;
 99 Begin
100  assign(input,‘input.in‘);reset(input);
101   readln(t);
102   for i:=1 to 4 do
103    begin
104      aj[i,0]:=1;
105      for j:=1 to di[i] do
106        aj[i,j]:=aj[i,j-1]*j mod di[i];    //预处理 i! mod di[i]的值 (i<=di)
107    end;
108   for i:=1 to t do
109    begin
110      readln(n,m);
111      main;
112      writeln(pow(m,ans,prime));
113    end;
114 end.
115
116  
时间: 2024-10-06 22:50:34

bzoj 2313 分组 2012-01-15的相关文章

【谜客帝国】第145届芭比娃娃主擂谜会(2019.01.15)

[谜客帝国]第145届芭比娃娃主擂谜会(2019.01.15) 主持:瓷   计分:默沫 1. 同心十八载,白首居河东(2字2019亚洲杯中国球员)石柯 2. 王朗气极坠地死(3字方位字)骂下马 [注:典据<三国演义>93回,“王朗听罢,气满胸膛,大叫一声,撞死于马下.”] 3. 城头长弓搭白羽(2字宋词人)张翥 4. 重门折屐未曾进(成语)格格不入 [注:重门.折屐,皆为谜格.] 5.“石城古岸头”(2字国家森林公园)圭山 6. 凯撒大帝显露出愤怒(4字<诗经>名句)七月流火 [

2015.01.15(android AsyncTask)

参考网址:http://www.cnblogs.com/devinzhang/archive/2012/02/13/2350070.html 1 /* 2 * Params 启动任务执行的输入参数,比如HTTP请求的URL. 3 * Progress 后台任务执行的百分比. 4 * Result 后台执行任务最终返回的结果,比如String 5 * 6 * doInBackground(Params…) :后台执行,比较耗时的操作都可以放在这里.注意这里不能直接操作UI. 7 * 此方法在后台线

bzoj 2753 [SCOI 2012] 滑雪与时间胶囊 - Prim

题目传送门 传送点I 传送点II 题目大意 给定一个有$n$个点$m$条边的图,每个点有一个高度$h_{i}$,能从$u$经过一条边到达$v$,当且仅当存在一条边是$(u, v)$或$(v, u)$,且$h_{u}\geqslant h_{v}$.问1号点能到达的所有点的最小树形图的边权和. 第一问沙雕问题.直接一个搜索水过. 第二问,好像是最小树形图.看着数据范围,嗯,别想朱-刘了. 感觉可以直接Prim.于是愉快地WA了一发.来回顾一下Prim算法的正确性证明 可以不妨设图中所有边的权重都不

[BZOJ 2790] [POI 2012] Distance

题意 给定长度为 n 的序列 a[1], a[2], ..., a[n] . 对于每个数 i , 求出 j , 满足 dist(a[i], a[j]) 最小, 且 i != j . dist(x, y) 表示由 x 变为 y 的最小步数, 每次变换可以乘上素数 p , 或除以素数 p . 2 <= n <= 100000 , 1 <= a[i] <= 1000000 . 分析 从前往后扫一遍, 从后往前扫一遍, 来满足 i != j 的条件. 记 Min[i] 表示访问到点 i 的

BZOJ 2750 HAOI 2012 Road 高速公路 最短路

题意: 给出一个有向图,求每条边有多少次作为最短路上的边(任意的起始点). 范围:n <= 1500, m <= 5005 分析: 一个比较容易想到的思路:以每个点作为起点,做一次SPFA,记f[i]表示从点S到达点i的最短路数,g[i]表示从点i到达点T的最短路数. 那么对于任意一条边,答案就是∑f[u]*g[v] 剩下的问题就是f.g怎么求. f必须从前面的递推过来,如果前面的没有递推完,那么就不能递推当前点,需要记录每个点可以从多少个点递推过来,这个一次dfs就可以完成. g可以记忆化搜

BZOJ #2669 \ CQOI 2012 局部最小值

题目描述: 在一个N * M的矩阵中填入1 ~ N * M的数,并限制一些位置为周围9个格中最小的,而其它位置不能满足这个条件. 解题思路: 考虑dp,F[i][s]表示填了前i个数,限制位置的填数状态为s,cnt[s]表示限制位置的状态为s时,可以填数的位置+限制位置已填数的数量. 那么 F[i][s] = F[i - 1][s] * (cnt[s] - i + 1) + ∑p∈s F[i - 1][s - p]. 但这样会忽略一些非限制的点满足了限制条件的情况.那我们就dfs把一些非限制点当

[BZOJ 2730][HNOI 2012] 矿场搭建

2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2113  Solved: 979[Submit][Status][Discuss] Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用

51 nod 1007 正整数分组 (简单01背包)

http://www.51nod.com/onlineJudge/questionCode.html#problemId=1007&noticeId=15020 求出n个数的和sum,然后用sum/2作为背包容量,让n个数去放,求出一个最大价值,那么这就是其中一组的和,另外一组的和就是sum-dp[sum/2]; 注意这里的体积和价值都是a[i]; 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath&

[2015.01.15]分享一些软件....不定期添加

1.激活类 KMSAuto.Net.2014.v1.3.4 下载:http://www.colafile.com/file/4232530 支持: Windows 8.1 Single Language;Windows 8.1 Core;Windows 8.1 Core N;Windows 8.1 Pro WMC;Windows Embedded 8.1 Industry Pro;Windows Server 2012 R2 Standard;Windows Server 2012 R2 Dat