• poj 3734 Blocks 快速幂+费马小定理+组合数学


    题目链接

    题意:有一排砖,可以染红蓝绿黄四种不同的颜色,要求红和绿两种颜色砖的个数都是偶数,问一共有多少种方案,结果对10007取余。

    题解:刚看这道题第一感觉是组合数学,正向推了一会还没等推出来队友就打表找到公式了,然后我就写了一个快速幂加个费马小定理就过了去看别的题了,赛后找到了一个很不错的博客:传送门,原来这道题也可以用DP+矩阵快速幂AC。下面说下组合数学的做法:

    首先一共有4^n种情况,我们减去不符合条件的情况就行了,从中取k个进行染红绿色一共C(n,k)种情况,剩下的蓝黄色一共有2^(n-k)种情况,接下来对k的奇偶进行分类讨论。(借用下博客里的公式)

    如果k为奇数,红色和绿色的数量为一奇一偶:2 * (c(k, 1) + c(k, 3) + c(k, 5) +……)* c(n, k) * 2^(n - k)   (其中要乘以2,是因为可以分别选择红、绿色为奇数)
    如果k为偶数,红色和绿色的数量全部为奇数:(c(k, 1) + c(k, 3) + c(k, 5) +……)* c(n, k) * 2^(n - k) (这里不需要乘以2)
    而 c(k, 1) + c(k, 3) + c(k, 5) +…… = 2^(k - 1)
    所以,最后的表达式为:
    4^n - 2^n*c(n, 1) - 2^(n - 1)*c(n, 2) - 2^n*c(n, 3) - 2^(n-1)*c(n, 4)-……
    = 4^n - 2^n*2^(n-1) - 2^(n-1)*(2^(n-1)-1)
    = 4^(n-1) + 2^(n-1)
    在计算过程中我们发现k奇数的时候没有问题是 2*2^(n-1)*2^(n-1)
    k偶数的时候要把k=0的情况算上所以要减去一个1,因为k=0是符合情况的不需要减去,这样就没问题了。
    另外这题不用费马小定理也能AC。
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    const ll mod=10007;
    ll n;
    ll pow1(ll a,ll b)
    {
        ll ans=1;
        while(b)
        {
            if(b&1)
            ans=ans*a%mod;
            b>>=1;
            a=a*a%mod;
        }
        return ans;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%lld",&n);
            n%=(mod-1);
            if(n==0) n=mod-1;
            ll ans=pow1(2,n-1);
            ans=(ans*ans%mod+ans)%mod;
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    logging模块、sys模块、shelve模块
    re模块、hashlib模块
    包、常用模块
    模块
    迭代器、生成器、递归、二分法
    函数对象、函数嵌套、名称空间与作用域、闭包函数、装饰器
    函数
    文件处理
    字符编码
    Djiango导读
  • 原文地址:https://www.cnblogs.com/Ritchie/p/5939024.html
Copyright © 2020-2023  润新知