• ZOJ3690—Choosing number


    题目链接:https://vjudge.net/problem/ZOJ-3690

    题目意思: 有n个人,每个人可以从m个数中选取其中的一个数,而且如果两个相邻的数相同,则这个数大于等于k,问这样的数一共有多少种选择,结果取模。

    思路:可能是算递推式子的能力还不够吧?没有推出来。这里我们我们运用划分的思想定义F[i]表示有i个人且最后一个人选的数组大于k选择数量,G[i]表示有i个人且最后一个人选的数组小于等于k的数量。

    我们可以得到以下递推式子:

    F[i]=(m-k)*(F[i-1]+G[i-1]),注:第i个人选择的数大于k,当然是i-1个人最后一个人选择的数大于k和最后一个人小于等于k的数量之和乘以大于k的数的数量,因为第i个人选择的是大于k的数,所以不被题目的限制条件限制。

    G[i]=k*F[i-1]+(k-1)*G[i-1],注:第i个人选择的数小于等于k,当然是i-1个人最后一个人选择大于k的数量乘以k加上i-1个人最后一个人选择小于等于k,为了让相邻的选择不同,所以乘以(k-1)。

    答案就是G[n]+F[n]。

    算递推式子的时候,看到这种以某个数k为限制的时候,应该以k为划分去思考问题。对今后算递推式子也算有点启发吧。

    代码:(有了递推式子以后代码就很简单了,套路的矩阵快速幂)

     1 //Author: xiaowuga
     2 #include <bits/stdc++.h>
     3 #define maxx INT_MAX
     4 #define minn INT_MIN
     5 #define inf 0x3f3f3f3f
     6 #define size 2
     7 #define MOD 1000000007
     8 using namespace std;
     9 typedef long long ll;
    10 ll a,b,c;
    11 struct Matrix{
    12     ll mat[3][3];
    13     void clear(){
    14         memset(mat,0,sizeof(mat));
    15     }
    16     Matrix operator * (const Matrix & m) const{
    17         Matrix tmp;
    18         for(int i=0;i<size;i++)
    19             for(int j=0;j<size;j++){
    20                 tmp.mat[i][j]=0;
    21                 for(int k=0;k<size;k++){
    22                     tmp.mat[i][j]+=mat[i][k]*m.mat[k][j]%MOD;
    23                     tmp.mat[i][j]%=MOD;
    24                 }
    25             }
    26         return tmp;
    27     }
    28 };
    29 Matrix POW(Matrix m,ll k){
    30     Matrix ans;
    31     ans.clear();
    32     for(int i=0;i<size;i++) ans.mat[i][i]=1;
    33     while(k){
    34         if(k&1) ans=ans*m;
    35         k/=2;
    36         m=m*m;
    37     }
    38     return ans;
    39 }
    40 int main() {
    41     ios::sync_with_stdio(false);cin.tie(0);
    42     while(cin>>a>>b>>c){
    43         Matrix m;
    44         m.clear();
    45         m.mat[0][0]=m.mat[0][1]=b-c;
    46         m.mat[1][0]=c;m.mat[1][1]=c-1;
    47         Matrix ans=POW(m,a-1);
    48         ll ans1=0,ans2=0;
    49         ans1=((ans.mat[0][0]*(b-c))%MOD+(ans.mat[0][1]*c)%MOD)%MOD;
    50         ans2=((ans.mat[1][0]*(b-c))%MOD+(ans.mat[1][1]*c)%MOD)%MOD;
    51         cout<<(ans1+ans2)%MOD<<endl;
    52     }
    53     return 0;
    54 }
    View Code
  • 相关阅读:
    Mysql 一次性备份导出/导入恢复所有数据库
    MySQL数据备份之mysqldump使用
    mysql数据库误删除后的数据恢复操作说明
    Qt的模态对话框和非模态对话框 经常使用setAttribute (Qt::WA_DeleteOnClose)
    Qt paintEvent绘制窗体 注意Qt::WA_PaintOutsidePaintEvent 只是适用于X11,其他系统均无效
    Building PySide on Microsoft Windows
    浅议Delphi中的Windows API调用(举的两个例子分别是String和API,都不错,挺具有代表性)
    Qt多线程学习-用例子来理解多线程
    Nutch之简介与安装
    RPC框架实现
  • 原文地址:https://www.cnblogs.com/xiaowuga/p/7356268.html
Copyright © 2020-2023  润新知