• bzoj 1902: Zju2116 Christopher lucas定理 && 数位DP


    1902: Zju2116 Christopher

    Time Limit: 1 Sec  Memory Limit: 64 MB
    Submit: 172  Solved: 67
    [Submit][Status][Discuss]

    Description

    给定n个元素,要从中间选择m个元素有多少种方案呢?答案很简单,就是C(n,m)。如果一个整数m(0≤m≤n),C(n,m)是某一个质数p的倍数,那么这个m就是讨厌的数字,现在给定了p和n,求有多少个讨厌的数字。

    Input

    第一行是一个正整数n,(1≤n≤10100)。输入的第二行是一个质数p(1≤p≤107)。

    Output

    只有一行,表示讨厌的数字的个数。

    Sample Input

    6
    2

    Sample Output

    3

    HINT

    30%的数据里,n≤1000; 100%的数据里,n≤10^100

    第一次写lucas定理,觉得非常“机智”

    将n,m分别分解p进制,发现如果某一位n[i]<m[i],则余数为0

    注意,这里p非常大,所以一般数位dp中for一遍0到p是不可取的,要特殊判断关键点,对于[0,p-1]中转移相同的一起处理。

    import sys;
    def deal(x,y):
        x=(x+y)%p;
    sys.stdin=open("input.txt","r");
    n=int(raw_input());
    p=int(raw_input());
    a=[];
    while (n):
        a.append(n%p);
        n/=p;
    for i in range(0,len(a)/2):
        a[i],a[len(a)-i-1] = a[len(a)-i-1],a[i];
    dp = [[[0 for k in range(0,2)] for j in range(0,2)] for i in range(0,len(a)+2)];
    dp[0][0][1]=a[0];
    dp[0][0][0]=1;
    for i in range(1,len(a)):
        for j in range(0,2):
            for k in range(0,2):
                #print i,j,k;
                if (dp[i-1][j][k]==0):continue;
                if (k==0):
                    dp[i][j][True] += dp[i-1][j][k]*a[i];
                    dp[i][j][False] += dp[i-1][j][k];
                else:
                    dp[i][j][True] += dp[i-1][j][k]*(a[i]+1);
                    dp[i][True][True] += dp[i-1][j][k]*(p-a[i]-1);
    print (dp[len(a)-1][1][0]+dp[len(a)-1][1][1]);
  • 相关阅读:
    2017.4.11下午学习内容
    2017.4.11上午学习内容
    2017.4.10下午学习内容
    2017.4.7下午学习内容
    2017.4.7号学习内容
    2017.4.6下午学习报告
    2017.4.6上午学习报告
    2017.3.31下午学习报告
    2017.3.31上午学习报告
    tornado的使用-日志篇
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4462836.html
Copyright © 2020-2023  润新知