CF div2 341-E

来源:互联网 发布:以史为鉴 可以知兴替 编辑:程序博客网 时间:2024/05/17 21:40
感觉自己太弱了……cf div2都只能做3题哈哈,下半年区域赛没有着落~

    这题看到就感觉变量很多,可能是因为前段时间做了数论的题,看到这题想用剩余定理;
想通过找规律,发现循环节,每变化一次对模数的变化,来进行统计,问题在于1.可能没有规律2.可能还是要一种情况一种情况算

看了答案之后发现,可以用矩阵优化的DP,真是厉害,因为比如前n个模x的值已知,*10之后再加一个数,模x就也好算了
要充分利用x比较小的条件,利用模运算……(当时自己为什么没想到)

代码参考了http://blog.csdn.net/jzhang1/article/details/50628041#
矩阵快速幂的模板还是很棒的

如果想到了dp的方法,F[i][(c * 10 + num) % x] += F[i - 1][c]
想用矩阵快速幂来求得话,想要使F[I][K] = F[0][K]  *( MATRIX^B)显然不靠谱,所以要找到F[I] = F[0] * (MATRIX^B)
然后F[I] = F[I-1] * MATRIX,然后找到F[I-1][K] 与 MATRIX的对应元素的关系,做一个预处理,就好了。
上参考别人代码后自己的代码……

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#define Mod 1000000007using namespace std;int p,k,no_box,no_digit;//矩阵快速幂 int cnt[10];struct Matrix {  //这样的拷贝能不能做到深拷贝?!?     long long val[105][105];  //可能会超出int     Matrix () {memset(val,0,sizeof(val));}  //无参数构造函数     friend Matrix operator *(Matrix x,Matrix y) {          Matrix Ans;          for(int i = 0;i < p;i ++)              for(int j = 0;j < p;j ++)                  for(int k = 0;k < p;k ++){                     Ans.val[i][j] += x.val[i][k] * y.val[k][j];                      Ans.val[i][j] %= Mod;                  }          return Ans;      }      friend Matrix operator^(Matrix X,int Y) {          Matrix Ans;          for(int I = 0;I <= p - 1;I ++)              Ans.val[I][I] = 1;          while(Y > 0)           {              if(Y % 2 == 1) Ans = Ans * X;             X = X * X;             Y = Y >> 1;          }          return Ans;      }  }A,B;int  main(){int tem;cin >> no_digit >> no_box >> k >> p;memset(cnt,0,sizeof(cnt));for (int i = 0; i < no_digit; i++){cin >> tem;cnt[tem]++;}for(int i = 0; i < p; i++)for(int j = 0; j < p; j++)for(int k = 1; k <= 9; k++)if (cnt[k] > 0  && ((i * 10 + k) % p) == j)B.val[i][j] += cnt[k];    A.val[0][0] = 1;//初始条件(要想清楚,或者先算出1时的情景) A = A * (B^no_box);cout << A.val[0][k] << '\n';return 0;}

0 0
原创粉丝点击