zoukankan      html  css  js  c++  java
  • 【USACO 2020 January Platinum】Non-Decreasing Subsequences (前缀积+矩阵的逆)

    https://gmoj.net/senior/#main/show/6557

    刚好前段时间学了矩阵逆的板,拿这题实践一下。

    当然这个矩阵比较简单,好像是可以直接手推矩阵的逆是什么。

    时间复杂度:(O(k^4+n*k^3+Q*k^2))

    Code

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int mo = 1e9 + 7;
    
    ll ksm(ll x, ll y) {
    	ll s = 1;
    	for(; y; y /= 2, x = x * x % mo)
    		if(y & 1) s = s * x % mo;
    	return s;
    }
    
    struct P {
    	int a[21][21];
    	P() { memset(a, 0, sizeof a);}
    } I;
    
    int w;
    
    P operator * (P a, P b) {
    	P c = P();
    	fo(k, 1, w) fo(i, 1, k) if(a.a[i][k])
    		fo(j, k, w) c.a[i][j] = (c.a[i][j] + (ll) a.a[i][k] * b.a[k][j]) % mo;
    	return c;
    }
    
    const int N = 50005;
    
    int n, a[N];
    
    P b[21], c[21];
    
    P inv(P a) {
    	P b = I;	
    	fo(i, 1, w) {
    		int u = -1;
    		fo(j, i, w) if(a.a[i][i]) { u = j; break;}
    		fo(j, 1, w) swap(a.a[i][j], a.a[u][j]), swap(b.a[i][j], b.a[u][j]);
    		ll x = ksm(a.a[i][i], mo - 2);
    		fo(j, 1, w) a.a[i][j] = (ll) a.a[i][j] * x % mo, b.a[i][j] = (ll) b.a[i][j] * x % mo;
    		fo(j, 1, w) if(i != j && a.a[j][i]) {
    			x = -a.a[j][i];
    			fo(k, 1, w) {
    				a.a[j][k] = (a.a[j][k] + (ll) a.a[i][k] * x) % mo;
    				b.a[j][k] = (b.a[j][k] + (ll) b.a[i][k] * x) % mo;
    			}
    		}
    	}
    	return b;
    }
    
    P s1[N], s2[N];
    
    int main() {
    	scanf("%d %d", &n, &w);
    	fo(i, 1, w) I.a[i][i] = 1;
    	fo(i, 1, w) {
    		fo(j, 1, w) b[i].a[j][j] = 1;
    		fo(j, 1, i) b[i].a[j][i] ++;
    		c[i] = inv(b[i]);
    	}
    	s1[0] = s2[0] = I;
    	fo(i, 1, n) {
    		scanf("%d", &a[i]);
    		s1[i] = s1[i - 1] * b[a[i]];
    		s2[i] = c[a[i]] * s2[i - 1];
    	}
    	int Q, x, y;
    	scanf("%d", &Q);
    	fo(ii, 1, Q) {
    		scanf("%d %d", &x, &y);
    		ll s = 0;
    		fo(k, 1, w) fo(j, 1, w)
    			s = (s + (ll) s2[x - 1].a[1][k] * s1[y].a[k][j]) % mo;
    		s = (s % mo + mo) % mo;
    		pp("%lld
    ", s);
    	}
    }
    
  • 相关阅读:
    sql中实现先排序后分组
    mysql中的锁机制之概念篇
    PHP对程序员的要求更高
    给初学PHP的学习线路和建议
    设计模式六大原则
    Mysql忘记密码怎么办
    数据库 sql
    精准优化 if…else ,干掉,过多,烂代码!
    JDK1.8 新特性(全)
    mysql 如何修改 删除 添加 表主键
  • 原文地址:https://www.cnblogs.com/coldchair/p/12680657.html
Copyright © 2011-2022 走看看