Qiuqiqiu  
不管道路多么崎岖坎坷,我永远不停下追逐梦想的脚步!

hdu 3037 Saving Beans http://acm.hdu.edu.cn/showproblem.php?pid=3037     2012-12-8

Lucas 大组合数取模 c(n+m,m)%p p为质数

p为质数

n=a0*p^0+a1*p^1+...+ak*p^k

m=b0*p^0+b1*p^1+...+bk*p^k

c(n,m)=c(a0,b0)*c(a1,b1)*...*c(ak,bk)

inv(x,p)=powmod(x,p-2,p)

View Code
 1 #include <cstdio>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 const int P=100010;
 6 LL fact[P];
 7 void getfact(int p)
 8 {
 9     fact[0]=1;
10     for(int i=1;i<p;i++)
11         fact[i]=fact[i-1]*i%p;
12 }
13 LL powmod(LL x,LL y,LL p)
14 {
15     LL s=1,t=x;
16     while(y>0)
17     {
18         if(y&1) s=s*t%p;
19         t=t*t%p;
20         y>>=1;
21     }
22     return s;
23 }
24 LL lucas(LL n,LL m,LL p)
25 {
26     LL ans=1;
27     while(n && m)
28     {
29         LL a=n%p, b=m%p;
30         if(a<b) return 0;
31         LL c=fact[a]*powmod(fact[b]*fact[a-b]%p,p-2,p)%p;
32         ans=ans*c%p;
33         n/=p; m/=p;
34     }
35     return ans;
36 }
37 int main()
38 {
39     int T;
40     scanf("%d",&T);
41     while(T--)
42     {
43         int n,m,p;
44         scanf("%d%d%d",&n,&m,&p);
45         getfact(p);
46         int ans=(int)lucas(n+m,m,p);
47         printf("%d\n",ans);
48     }
49     return 0;
50 }

 

 

hdu 4373 Mysterious For http://acm.hdu.edu.cn/showproblem.php?pid=4373    2012-12-8

for a0=0 to n   for a1=a0+1 to n ...  for am=a(m-1)+1 to n  s++;   s加了c(n,m)次 刚好遍历所有组合

所以for a0=0 to n   for a1=a0 to n ...  for am=a(m-1) to n  s++;   s加了c(n+m,m)次

分解质因数求组合数 364875103=97*3761599不能求逆元

 

View Code
 1 #include <cstdio>
 2 #include <map>
 3 using namespace std;
 4 
 5 typedef long long LL;
 6 const int md=364875103;
 7 map<int,int> mp;
 8 LL c(LL n,LL m,LL p)
 9 {
10     mp.clear();
11     for(int k=1;k<=m;k++)
12     {
13         int x=n-k+1;
14         for(int i=2;i*i<=x;i++)
15             for(;x%i==0;x/=i) mp[i]++;
16         if(x>1) mp[x]++;
17         x=k;
18         for(int i=2;i*i<=x;i++)
19             for(;x%i==0;x/=i) mp[i]--;
20         if(x>1) mp[x]--;
21     }
22     LL s=1;
23     for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++)
24     {
25         int a=it->first,c=it->second;
26         for(int i=0;i<c;i++) s=s*a%p;
27     }
28     return s;
29 }
30 int main()
31 {
32     int T,C=0;
33     scanf("%d",&T);
34     while(T--)
35     {
36         int n,m;
37         scanf("%d%d",&n,&m);
38         int a[20],k;
39         scanf("%d",&k);
40         for(int i=0;i<k;i++) scanf("%d",&a[i]);
41         a[k]=m;
42         LL ans=1;
43         for(int i=1;i<=k;i++)
44             ans=ans*c(n+a[i]-a[i-1]-1,a[i]-a[i-1],md)%md;
45         printf("Case #%d: %d\n",++C,(int)ans);
46     }
47     return 0;
48 }

 

 

 

hdu 4930 Number Sequence http://acm.hdu.edu.cn/showproblem.php?pid=4390

大意:a1*a2*...*an=b1*b2*...*bn,给出n和b,求a的方案数(ai>1)

容斥原理分解质因数map,将m件物品放入n个盒子,盒子可以为空的方案数为c(n-1+m,n-1) 插板法 类似与x1+x2+...+xn=m的方案数

View Code
 1 #include <cstdio>
 2 #include <map>
 3 using namespace std;
 4 
 5 typedef long long LL;
 6 const int N=41;
 7 const int md=(int)(1e9+7.5);
 8 map<int,int> pri;
 9 int c[N][N];
10 void getc()
11 {
12     c[0][0]=1;
13     for(int i=1;i<N;i++)
14     {
15         c[i][0]=c[i][i]=1;
16         for(int j=1;j<i;j++)
17             c[i][j]=(c[i-1][j-1]+c[i-1][j])%md;
18     }
19 }
20 void add(int x)
21 {
22     for(int i=2;i*i<=x;i++)
23     {
24         while(x%i==0)
25         {
26             pri[i]++;
27             x/=i;
28         }
29     }
30     if(x>1) pri[x]++;
31 }
32 int put(int n)
33 {
34     LL s=1;
35     for(map<int,int>::iterator it=pri.begin();it!=pri.end();it++)
36     {
37         int cnt=it->second;
38         s=s*c[n-1+cnt][n-1]%md;
39     }
40     return s;
41 }
42 int main()
43 {
44     int n;
45     getc();
46     while(~scanf("%d",&n))
47     {
48         pri.clear();
49         for(int i=0;i<n;i++)
50         {
51             int b;
52             scanf("%d",&b);
53             add(b);
54         }
55         int ans=0;
56         for(int i=n,sign=1;i>0;i--,sign=-sign)
57         {
58             LL s=put(i);
59             ans=((LL)ans+c[n][i]*s*sign)%md;
60         }
61         ans=(ans+md)%md;
62         printf("%d\n",ans);
63     }
64     return 0;
65 }

 

 

posted on 2012-11-28 22:36  Qiuqiqiu  阅读(158)  评论(0编辑  收藏  举报