2 条题解

  • 3
    @ 2023-8-21 14:08:24

    image.pngimage

    #include <bits/stdc++.h>
    #define ll long long
    #define P 2009
    using namespace std;
    const int N=100;
    int n,m,k,s,t;
    struct Matrix{
    	ll a[N][N];
    	Matrix(){ memset(a,0,sizeof(a));}//构造函数,矩阵初始化全零 
    	Matrix operator*(Matrix &b)const{//重载乘法运算 
    		Matrix tmp;
    		for (int k=0;k<=m;++k)
    			for (int i=0;i<=m;++i)
    				for (int j=0;j<=m;++j)
    					(tmp.a[i][j]+=a[i][k]*b.a[k][j])%=P;
    		return tmp;
    	}
    }a,ans;
    void qpow(ll p){
    	for (int i=0;i<=m;++i)
    		ans.a[i][i]=1;//ans初始化为单位矩阵 
    	while (p){
    		if (p&1) ans=ans*a;
    		a=a*a;
    		p>>=1;
    	}
    }
    int main(){
    	freopen("in.txt","r",stdin);
    	cin>>n>>t;m=(n-1)*9+8;
    	char c;
    	for (int i=1;i<=n;++i)
    		for (int j=1;j<=n;++j){
    			cin>>c;
    			k=c-'0';
    			if (k) a.a[(i-1)*9][(j-1)*9+k-1]=1;//i号点向距离j号点k-1距离的点连边 
    		}
    	for (int i=1;i<=n;++i)
    		for (int j=1;j<=8;++j) a.a[(i-1)*9+j][(i-1)*9+j-1]=1;//每轮减少1的距离 
    	qpow(t);
    	cout<<ans.a[0][(n-1)*9];
    } 
    
    
    • 1
      @ 2023-8-16 22:06:55

      狗头上几个! 对于 100 % 100%100% 的数据解法 这100分很难拿,我做的时候调了一周呢。

      我们看到这t的数据范围时,就应该条件反射的想到时间复杂度应该是有个 log ⁡ t \log tlogt 的,事实的确如此。

      有人还是有点懵啊,怎么弄呢?

      这时候我们先来思考下一个前置问题:

      我们把每一条路的长度都改成1或0,其他都不变。 1 是不是感觉到了什么。 其实上面这个问题就是个矩阵快速幂吗。(不知道啥是“矩阵快速幂”的,尽请期待我的下一篇blog:矩阵快速幂)

      所以如果要解决上面这个问题的话我们会发现其实他的答案就是 G t G^t G t

      这里G为邻接矩阵。

      怎么把问题转换成刚才哪一种呢? 其实我们并不需要更改快速幂那一部分,只要改建图方式就行了(因为 n nn 很友好)

      怎么建图呢?

      我们可以这样建:就是比如有以下关系

      2 4 1 1 2 3 4 我们可以把它变成这样:

      1 a b c 2 3 4 这样虽然点数要多8倍,但起码比搜索好太多了,我们只需要给每个点都安排8个后继节点,然后每一个都像这样连(就像连面包板一样)

      那我们最后的时间复杂度便是矩阵乘法的复杂度乘上快速幂的那个 log ⁡ \loglog

      即整体复杂度: Θ ( ( 10 n ) 3 log ⁡ t ) \Theta((10n)^3\log t)Θ((10n) 3 logt)

      卡卡就能过,但是很容易卡常,千万小心,因为出题人很毒瘤。

      愉快地贴上代码

      #include <bits/stdc++.h>
      using namespace std;
      
      const int maxn = 100 + 20;
      const int mod = 2009;
      typedef long long ll;
      
      char s[15][15];
      int G[maxn][maxn];
      struct Matrix {
      int n, m;
      int a[maxn][maxn];
      Matrix() { memset(a, 0, sizeof a); }
      Matrix(int _n, int _m) {
      n = _n;
      m = _m;
      memset(a, 0, sizeof a);
      }
      };
      
      Matrix mul(Matrix &a, Matrix &b) {
      Matrix res(a.n, b.m);
      for (int i = 0; i < a.n; i++)
      for (int j = 0; j < b.m; j++)
      for (int k = 0; k < a.m; k++) {
      res.a[i][j] += a.a[i][k] * b.a[k][j];
      res.a[i][j] %= mod;
      }
      return res;
      }
      
      Matrix Pow(Matrix &base, int n) {
      Matrix res(base.n, base.n);
      for (int i = 0; i < base.n; i++) res.a[i][i] = 1;
      while (n) {
      if (n & 1) res = mul(res, base);
      base = mul(base, base);
      n >>= 1;
      }
      return res;
      }
      
      int main() {
      // freopen("lost.in", "r", stdin);
      // freopen("lost.out", "w", stdout);
      int n, k;
      scanf("%d%d", &n, &k);
      for (int i = 0; i < n; i++) scanf("%s", s[i]);
      Matrix G(10 * n - 1, 10 * n - 1);
      for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
      int now = s[i][j] - '0';
      if (now == 0) continue;
      G.a[10 * i + now - 1][10 * j] = 1;
      }
      }
      for (int i = 0; i < n; i++) {
      for (int j = 0; j < 8; j++) {
      G.a[10 * i + j][10 * i + j + 1] = 1;
      }
      }
      G = Pow(G, k);
      cout << G.a[0][(n - 1) * 10] << endl;
      return 0;
      }
      
      • 1

      信息

      ID
      378
      时间
      1000ms
      内存
      125MiB
      难度
      3
      标签
      递交数
      62
      已通过
      33
      上传者