您的位置:首页 > Web前端

ZOJ 3842 Cirno's Perfect Math Class (Kummer定理)

2015-06-20 05:49 302 查看
Cirno's Perfect Math Class

Time Limit: 2 Seconds     
Memory Limit: 65536 KB 
"Minnaa ~ Cirno no Sansuu Kyoushitsu Hajimaruyo ~ "
Cirno's perfect math class is fashionable over the world. But now, sadly, it must be stopped for some reason. In the last class,N students attended, and each student gave a gift to Cirno. But the gifts are too many so that
Cirno just want to takeK(K is non-negative) gifts away.
As we all know, Cirno loves the number ⑨. Assume there areP ways to take awayK gifts. IfP > 0 andP is a multiple of 9, Cirno will acceptK as an alternative plan. Now, Cirno want
to know how many plans that she has to think over.
Input
The number of test cases T(integer, about 50) will be given in the first line. ThenT lines follow. and each line contains a non-negative integerN(N <= 10^1000).
Output
One line for each case, the answer.
Sample Input
35190
Sample Output
063

Author: LIN, Hanzhao
Source: ZOJ Monthly, January 2015

题意:

给定n(n<=10^1000),求满足0<=k<=n且C(n,k)是9的倍数的k的个数。

分析:

考虑C(n,k)不是9的倍数的k的个数,分为两部分求解,

(1)C(n,k)不被3整除,

由Lucas定理知,若n的三进制表示为a[0]a[1]a[2]...a[s],则所求的个数为res=(a[0]+1)*(a[1]+1)*(a[2]+1)*...*(a[s]+1),

(2)C(n,k)被3整除但不被9整除,

这种情况比较麻烦,Lucas定理不能发挥作用,考虑使用更一般的Kummer定理,

根据Kummer定理,C(n,k)中3的幂次即为在三进制下n减去k时发生借位的次数,那么当C(n,k)恰被3整除时,n减k时恰好发生了一次借位,也就是说,有且仅有一个t,使得k的三进制表示的第t位严格大于n的第t位,且k的第t+1位严格小于n的第t+1位。枚举所有位置,注意到对每个位置计算贡献时,结果只有两个因式与res不同,如果不考虑大数运算的复杂度,可以O(1)计算贡献.

以上两种情况之和ans即为不满足条件的k的个数,输出n+1-ans即可,复杂度O((logn)^2)。

Kummer定理相关:

求Kummer定理知识_数学竞赛吧

库默尔定理_百度百科

关于组合数的几个整除问题_百度文库

代码:

import java.util.*;
import java.io.*;
import java.math.*;
public class Main
{
static public void main(String[] args)
{
Scanner cin=new Scanner(System.in);
int T=cin.nextInt();
for(int ca=1;ca<=T;ca++)
{
BigInteger n=cin.nextBigInteger();
String s=n.toString(3);
BigInteger res=BigInteger.ONE;
for(int i=0;i<s.length();i++)
{
res=res.multiply(BigInteger.valueOf(s.charAt(i)-'0'+1));
}
BigInteger ans=res;
for(int i=1;i<s.length();i++)
{
ans=ans.add(res.divide(BigInteger.valueOf(s.charAt(i-1)-'0'+1))
.divide(BigInteger.valueOf(s.charAt(i)-'0'+1))
.multiply(BigInteger.valueOf(s.charAt(i-1)-'0'))
.multiply(BigInteger.valueOf('2'-s.charAt(i))));
}
System.out.println(n.subtract(ans).add(BigInteger.ONE));
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: