poj 3146: Lucas 定理

一、常规方法
见poj 3219的方法,这一方法容易理解,只是超时。
对于输入的n、p,
for(i=0;i<=n;i++)
{
用前面的方法,分别计算n!、i!、(n-i)!中因子p的个数,再比较n!中因子p的个数与i!、(n-i)!中因子p的个数之和,来决定组合数C(n,i)是否能整除p;
如不能整除,计数器加1;
}
代码如下:
#include
using namespace std;
int jc(int N, int P)
{
int sum=0;
while(N)
{
sum=sum+N/P;
N=N/P;
}
return sum;
}
int n,m,p,ca=0;
int main()
{
while(scanf("%d%d",&p,&n))
{
if(p0 && n0)
break;
ca++;
int i,count=0;
int a=jc(n, p);
for(i=0;i<(n+1)/2;i++)
{
int b=jc(i, p);
int c=jc(n-i, p);
if(a<=b+c)
count++;
}
printf(“Case %d: %04d\n”,ca,2*count);
}
system(“pause”);
return 0;
}

二、Lucas定理
仍然超时,只能用Lucas定理,只看结论:
1、Lucas定理:
因为,对任何数有:n = n/pp + n%p(n/p取整)
所以:对任意数n和m,质因数p,则组合数c(n,m)与组合数C(n/p,m/p)C(n%p,m%p)同余。
也即是:令n=sp+q , m=tp+r .(q ,r ≤p)
那么:在这里插入图片描述
2、本题解法
而本题的大致解法是:
给n,p,n=ak
pk+a(k-1)*p(k-1)+…+a2
p^2+a1p+a0,也就是,n的p进制表示为(ak,…,a2,a1,a0)
那么,在组合数c(n,0),c(n,1)…c(n,n-1),c(n,n)中,不能被P整除的数一共有(a0+1)
(a1+1)(ak+1),

#include
using namespace std;
int main()
{
int p,n,ca=0;
while(cin>>p>>n)
{
if(p0 && n0)
break;
int ans=1;
while(n)
{
ans=ans*(n%p+1);
n=n/p;
if(ans>=10000)
ans=ans%10000;

	}
	printf("Case %d: %04d\n",++ca,ans);
}
system("pause");
return 0; 

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值