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

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

3
5
1
9
0

Sample Output

0
6
3
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));
        }
    }
}


发布了25 篇原创文章 · 获赞 20 · 访问量 5万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览