zoukankan      html  css  js  c++  java
  • 「SOL」NOI2016 Day1 解题报告

    第一次打 NOI,还是先把以前的 NOI 题刷一遍吧?


    # 目录


    # A. 优秀的拆分 excellent

    > Link 优秀的拆分 - LOJ

    如果能对每个位置求出以它开头/结尾的形如 AA 的串的数量,那这个问题就非常简单了。

    考虑如何对 AA 串计数。和另外一道题(忘了题目了)非常类似,那道题是回文串,将原串 (kL) 的位置设为关键点,任何长度为 (2L) 的回文串一定经过两个关键点。这道题则是任何 (|A|=L)AA 串都会经过两个关键点。

    SA 快速处理出两个前缀的 LCS 和两个后缀的 LCP。我们可以判断:

    png1

    —— 以 (S_1)(S_2) 这些位置开头存在长度为 (2L)AA 串,以 (T_1)(T_2) 这些位置结尾存在长度为 (2L)AA 串。

    差分计数即可。


    # B. 网格 grid

    > Link 网格 - LOJ

    看来做的题比较多还是有好处。有一类题要求最小化操作数量,看起来非常复杂,但是通过一些人类智慧可以发现最大答案其实很小,即存在简单的合法构造方案。这样将问题转化为「判断是否存在答案为 (x) 的可行解」。

    (称“跳蚤”为白格,“蛐蛐”为黑格)

    同样的道理,分析这道题。首先不难发现无解的情况只有:

    • 只有一个白格;
    • 只有两个白格且相邻。

    排除这两个情况,剩下的都有解。

    可以用至多 (4) 次操作把一个白格围起来,因此答案至多为 (4)。远远不够,我们还发现可以利用一个极大白格连通块的边角处,一个白格连通块必定存在“角”这种只需要两次操作就可以围起来的格子,因此答案至多为 (2)

    换句话说,答案只能是 (0,1,2)

    答案是 (0) 可以直接判断连通性(关于建图之后再分析),那么就只剩下判断答案是 (1) 还是 (2)
    直观上感觉 (2)(1) 难判断,的确如此。答案是 (1) 意味着只需要填一个格子就可以把原本的连通块割成多个……这不就是割点吗?

    可以暴力建出点、边数量都是 (mathcal O(nm)) 的图通过部分数据。

    我们只需要用到这张图的连通性以及可能的割点,显然图中有很多点是可以合并的:

    • 合并点不会改变原图连通性;
    • 如果两个点都不可能是割点,则可以合并,合并后的点不可能是原图的割点

    什么点可能是割点?必然是在周围(八联通)有一个黑格的白格。因此我们只需要把黑格周围的白格单独建点,其他的按行合并。如图:

    png2

    这样点数、边数都与黑格数量同阶,可以用 Tarjan 求割点判断答案,顺便还可以判断连通性。


    # C. 循环之美 cyclic

    久仰大名

    结论

    一个数 $A$ 是 $k$ 进制 $L$ 纯循环的充要条件是 $A imes k^L-A$ 是整数。

    如果 $A$ 表示成最简分数 $frac xy$,则上述条件等价于 $ymid k^L-1$。则 $A$ 是 $k$ 进制纯循环小数当且仅当 $k^Lequiv1pmod y$ 有 $Lgt 1$ 的解 $L$,运用某些数论知识(忘了,但是我记得住结论 awa)可以得到等价条件为 $k,y$ 互质。

    于是我们可以知道答案为:

    [sum_{x=1}^nsum_{y=1}^mig[(x,y)=1ig]ig[(y,k)=1ig] ]

    看着就很莫比乌斯反演,但是我自己做的时候思路错了,不应该直接把两个条件都反演掉(只能做到 (mathcal O(nsigma_0(k))))……

    UPD. 两个条件都反演掉也能做,将 ([(y,k)=1]) 反演后设 (tmid (y,k)),则 (y) 的可取值的数量为 (lfloor frac m{mathrm{lcm}(t,d)} floor),再对 lcm 进行反演:

    [egin{aligned} &sum_{d=1}^nmu(d)lfloor frac nd floorsum_{dmid j}^{jle m}[(j,k)=1]\ =&sum_dmu(d)lfloor frac nd floorsum_{dmid j}sum_{tmid k,tmid j}mu(t)\ =&sum_dmu(d)lfloor frac nd floorsum_{tmid k}lfloor frac m{mathrm{lcm}(t,d)} floor\ end{aligned} ]

    枚举 (t,d) 的 GCD 为 (p)

    [sum_dmu(d)lfloor frac nd floorsum_{tmid k}sum_plfloor frac {mp}{td} floorig[(t,d)=pig] ]

    再反演掉,第二行是转为枚举 (r=qp)

    [egin{aligned} &sum_dmu(d)lfloor frac nd floorsum_{tmid k}sum_plfloor frac {mp}{td} floorsum_{qmidfrac dp,qmidfrac tp}mu(q)\ =&sum_dmu(d)lfloor frac nd floorsum_{tmid k}sum_{rmid d,rmid t}sum_{pmid r}mu( frac rp)lfloor frac{mp}{td} floor end{aligned} ]

    整理一下整除的关系:(pmid r o rmid t o tmid k),还有 (rmid d),简化一下式子,直接枚举 ((p,r,t))

    [egin{aligned} &sum_{pmid rmid tmid k}mu( frac rp)sum_{rmid d}^{dle n}mu(d)lfloor frac nd floorlfloor frac {mp}{td} floor end{aligned} ]

    后边的那个求和可以写为

    [f(n,m,r)=sum_{rmid d}mu(d)lfloor frac nd floorlfloor frac md floor ]

    继续推式子:

    [egin{aligned} f(n,m,r)&=sum_{d=1}^{lfloor n/r floor}mu(dr)lfloor frac n{dr} floorlfloor frac m{dr} floor\ &=sum_{d=1}^{lfloor n/r floor}mu(d)mu(r)ig[(r,d)=1ig]lfloor frac n{dr} floorlfloor frac m{dr} floor\ &=mu(r)sum_{t=1}^{lfloor n/r floor}mu(t)sum_{tmid d}^{lfloor n/r floor}mu(d)lfloor frac n{dr} floorlfloor frac m{dr} floor\ &=mu(r)sum_{t=1}^{lfloor n/r floor}mu(t)f(lfloor frac nr floor,lfloor frac mr floor, t) end{aligned} ]

    (r eq1) 时可以递归计算,只会递归 (mathcal O(log n)) 层,当 (r=1)

    [f(n,m,1)=sum_{d=1}^nmu(d)lfloor frac nd floorlfloor frac md floor ]

    可以数论分块+杜教筛。

    还是下面这个做法比较小清新……

    直接上正解吧,两个条件中取较简单的一个反演 —— (k) 是常数,所以尝试反演 ([(y,k)=1])

    [egin{aligned} &sum_{dmid k}mu(d)sum_{dmid y}^{yle m}sum_{x=1}^nig[(x,y)=1ig]\ =&sum_{dmid k}mu(d)sum_{y=1}^{lfloor m/d floor}sum_{x=1}^{n}ig[(x,d)=1ig]ig[(x,y)=1ig] end{aligned} ]

    注意到后面的式子和原问题很像,实际上令 (f(n,m,k))

    [f(n,m,k)=sum_{x=1}^nsum_{y=1}^mig[(x,y)=1ig]ig[(y,k)=1ig] ]

    则反演后的结果为:

    [f(n,m,k)=sum_{dmid k}mu(d)fBig(iglfloor frac mdig floor,n,dBig) ]

    递归处理 (dgt1) 的情况,直到 (nm=0) 答案为 (0);对于 (d=1)(k=1) 直接计算:

    [f(n,m,1)=sum_{x=1}^nsum_{y=1}^m[(x,y)=1]=sum_{d}lfloor frac nd floorlfloor frac md floormu(d) ]

    直接数论分块+杜教筛。


    # 小结

    A 题有一定思维难度,不过题目给的部分分比较生艹,(mathcal O(n^2)) 给到了 95pts,如果没有时间想正解拿了 95pts 也差不多了。

    B 题纯粹考实现,也就是建图那部分。只要把答案只有 (-1,0,1,2) 这一点想到,正解就呼之欲出了,只是看实现问题,预估将会是考场上用时最长的一道题。

    C 题的结论可以靠感知(背结论 awa)+暴力验证,我是写了一个 BSGS 来验证了 (500) 范围内是正确的,然后就默认结论没有错。不管怎么莫比乌斯反演,至少能够得到一个 (mathcal O(nsigma_0(k))) 的可以直接暴力算的式子,然后线性筛 (le2 imes10^7) 的就可以得到 84pts,应该是比较好的成绩了。说起来,要敢开数组,只要不爆空间,虽然看起来 (mathcal O(nsigma_o(k)))(n=2 imes10^7) 看起来很离谱,但是敢写就能过……


    # 源代码

    差点忘了
    几份代码写的时间间隔比较长,中途还改了码风……

    点击展开/折叠 excellent.cpp
    /*Lucky_Glass*/
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N = 30005;
    #define con(typ) const typ &
    
    int n, ncas;
    int elg2[N], cnts[N], cntt[N];
    char str[N];
    
    struct Sa {
    	int sa[N], rnk[N], nsa[N], nrnk[N], bin[N];
    	int hgt[N][20];
    	void clean(con(int) len) {
    		memset(bin, 0, sizeof bin);
    		for (int i = 1; i <= len; i++)
    			rnk[i] = nrnk[i] = 0;
    	}
    	void build(char *sstr, con(int) len) {
    		clean(len);
    		for (int i = 1; i <= len; i++) bin[sstr[i] - 'a' + 1]++;
    		for (int i = 1; i <= 26; i++) bin[i] += bin[i - 1];
    		for (int i = 1; i <= len; i++) sa[bin[sstr[i] - 'a' + 1]--] = i;
    		rnk[sa[1]] = 1;
    		for (int i = 2; i <= len; i++) {
    			rnk[sa[i]] = rnk[sa[i - 1]];
    			if ( sstr[sa[i]] != sstr[sa[i - 1]]) rnk[sa[i]]++;
    		}
    		#define ikey(i) ((i) > len ? 0 : rnk[i])
    		for (int l = 1; rnk[sa[len]] < len; l <<= 1) {
    			for (int i = 1; i <= len; i++) bin[rnk[sa[i]]] = i;
    			for (int i = len; i >= 1; i--)
    				if ( sa[i] > l )
    					nsa[bin[rnk[sa[i] - l]]--] = sa[i] - l;
    			for (int i = len - l + 1; i <= len; i++)
    				nsa[bin[rnk[i]]--] = i;
    			nrnk[nsa[1]] = 1;
    			for (int i = 2; i <= len; i++) {
    				nrnk[nsa[i]] = nrnk[nsa[i - 1]];
    				if ( ikey(nsa[i]) != ikey(nsa[i - 1])
    					|| ikey(nsa[i] + l) != ikey(nsa[i - 1] + l) )
    						nrnk[nsa[i]]++;
    			}
    			swap(rnk, nrnk), swap(sa, nsa);
    		}
    		for (int i = 1, j = 0; i <= len; i++) {
    			if ( j ) j--;
    			while ( rnk[i] < len && sstr[i + j] == sstr[sa[rnk[i] + 1] + j] ) j++;
    			hgt[rnk[i]][0] = j;
    		}
    		// for (int i = 1; i < len; i++)
    			// printf("%d%c", hgt[i][0], i == len - 1 ? '
    ' : ' ');
    		for (int i = len; i; i--)
    			for (int j = 1; j < 20; j++)
    				if ( i + (1 << (j - 1)) <= len )
    					hgt[i][j] = min(hgt[i][j - 1], hgt[i + (1 << (j - 1))][j - 1]);
    				else hgt[i][j] = hgt[i][j - 1];
    	}
    	int query(con(int) s, con(int) t) {
    		if ( s > n || t > n ) exit(-1);
    		int ss = rnk[s], tt = rnk[t];
    		if ( ss > tt ) swap(ss, tt);
    		tt--;
    		int l = elg2[tt - ss + 1];
    		return min(hgt[ss][l], hgt[tt - (1 << l) + 1][l]);
    	}
    } tol, tor;
    
    void init() {
    	elg2[1] = 0;
    	for (int i = 2; i < N; i++)
    		elg2[i] = elg2[i >> 1] + 1;
    }
    int matchR(con(int) s, con(int) t) {
    	if ( s > n || t > n ) return 0;
    	return tor.query(s, t);
    }
    int matchL(con(int) s, con(int) t) {
    	return tol.query(n - s + 1, n - t + 1);
    }
    int main() {
    	// freopen("input.in", "r", stdin);
    	init();
    	scanf("%d", &ncas);
    	while ( ncas-- ) {
    		scanf("%s", str + 1);
    		n = (int) strlen(str + 1);
    		for (int i = 1; i <= n; i++) cntt[i] = cnts[i] = 0;
    		tor.build(str, n);
    		reverse(str + 1, str + 1 + n);
    		tol.build(str, n);
    		for (int i = 1; i <= n; i++) {
    			for (int j = i; j + i <= n; j += i) {
    				int pl = matchL(j, j + i), pr = matchR(j + 1, j + i + 1);
    				pl = min(pl, i), pr = min(pr, i - 1);
    				int tmp = pr + pl - i + 1;
    				if ( tmp > 0 ) {
    					// printf("%d: start at [%d, %d]
    ", i, i - pl + 1, i - pl + tmp);
    					// printf("%d: end at [%d, %d]
    ", i, i - pl + 2 * i, i - pl - 1 + tmp + 2 * i);
    					cnts[j - pl + 1]++, cnts[j - pl + 1 + tmp]--;
    					cntt[j - pl + 2 * i]++, cntt[j - pl + tmp + 2 * i]--;
    				}
    			}
    		}
    		for (int i = 1; i <= n; i++) cnts[i] += cnts[i - 1], cntt[i] += cntt[i - 1];
    //		for (int i = 1; i <= n; i++)
    //			printf("start at %d = %d
    ", i, cnts[i]);
    		long long ans = 0;
    		for (int i = 1; i < n; i++)
    			ans += 1ll * cnts[i + 1] * cntt[i];
    		printf("%lld
    ", ans);
    	}
    	return 0;
    }
    
    点击展开/折叠 grid.cpp
    /*Lucky_Glass*/
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int DIR[9][2] = {
      {-1, -1}, {-1, 0}, {-1, 1},
      {0, -1}, {0, 0}, {0, 1},
      {1, -1}, {1, 0}, {1, 1}
    };
    
    inline int rin(int &r) {
      int b = 1, c = getchar(); r = 0;
      while ( c < '0' || '9' < c ) b = c == '-' ? -1 : b, c = getchar();
      while ( '0' <= c && c <= '9' ) r = (r * 10) + (c ^ '0'), c = getchar();
      return r *= b;
    }
    
    const int N = 1e5 + 10, NP = N * 20, NE = N * 80;
    #define con(typ) const typ &
    
    struct Graph {
      int head[NP], to[NE], nxt[NE], ncnt, np;
      void addEdge(con(int) u, con(int) v) {
        int p = ++ncnt, q = ++ncnt;
        to[p] = v, nxt[p] = head[u], head[u] = p;
        to[q] = u, nxt[q] = head[v], head[v] = q;
      }
      inline int operator [] (con(int) u) const {return head[u];}
    } gr;
    
    struct SPNode {
      int x, y, tag;
      bool operator < (con(SPNode) p) const {
        if ( x == p.x ) return y < p.y;
        return x < p.x;
      }
    } nod[N * 9];
    
    bool isans1;
    int ncas, n, m, nc, nnod, itmp, ndfn;
    int dfn[NP], low[NP];
    bool ptag[NP];
    int tmp[2][NP][3], ntmp[2];
    pair<int, int> pos[N];
    
    void dfs(con(int) u) {
      bool iscut = false;
      int cntson = 0;
      dfn[u] = low[u] = ++ndfn;
      for (int it = gr[u]; it; it = gr.nxt[it]) {
        int v = gr.to[it];
        if ( dfn[v] ) low[u] = min(low[u], dfn[v]);
        else {
          cntson++;
          dfs(v);
          low[u] = min(low[u], low[v]);
          if ( low[v] >= dfn[u] )
            if ( ptag[u] )
              iscut = true;
        }
      }
      if ( iscut )
        isans1 |= (u != 1 || cntson > 1);
    }
    void newTemp() {itmp ^= 1, ntmp[itmp] = 0;}
    void setTemp(con(int) l, con(int) r, con(bool) tag) {
      int p = ++gr.np;
      if ( p >= NP ) exit(0);
      dfn[p] = 0, gr.head[p] = 0;
      ptag[p] = tag;
      tmp[itmp][++ntmp[itmp]][0] = l, tmp[itmp][ntmp[itmp]][1] = r;
      tmp[itmp][ntmp[itmp]][2] = p;
    }
    void arrangeTemp() {
      for (int i = 1; i < ntmp[itmp]; i++)
        if ( tmp[itmp][i][1] + 1 == tmp[itmp][i + 1][0] )
          gr.addEdge(tmp[itmp][i][2], tmp[itmp][i + 1][2]);
      if ( !ntmp[0] || !ntmp[1] ) return;
      for (int i = 1, jl = 1, jr = 0; i <= ntmp[0]; i++) {
        while ( jr < ntmp[1] && tmp[1][jr + 1][0] <= tmp[0][i][1] ) jr++;
        while ( jl <= jr && tmp[1][jl][1] < tmp[0][i][0] ) jl++;
        for (int j = jl; j <= jr; j++)
          gr.addEdge(tmp[0][i][2], tmp[1][j][2]);
      }
    }
    
    bool bf[N];
    
    bool isNeg() {
      if ( 1ll * n * m - nc > 2 ) return false;
      if ( 1ll * n * m - nc <= 1 ) return true;
      #define id(x, y) ((x) * m - m + (y))
      for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
          bf[id(i, j)] = false;
      for (int i = 1; i <= nc; i++)
        bf[id(pos[i].first, pos[i].second)] = true;
      const int DIR[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
      for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++)
        if ( !bf[id(i, j)] )
          for (int k = 0; k < 4; k++) {
            int x = i + DIR[k][0], y = j + DIR[k][1];
            if ( 1 <= x && x <= n && 1 <= y && y <= m && !bf[id(x, y)] )
              return true;
          }
      return false;
      #undef id
    }
    int main() {
      rin(ncas);
      while ( ncas-- ) {
        ndfn = nnod = 0;
        gr.np = gr.ncnt = 0;
        itmp = 0;
        isans1 = false;
        //
        rin(n), rin(m), rin(nc);
        for (int i = 1; i <= nc; i++)
          rin(pos[i].first), rin(pos[i].second);
        if ( isNeg() ) {printf("-1
    "); continue;}
        sort(pos + 1, pos + 1 + nc);
        if ( m == 1 ) {
          int cnti = 0;
          if ( nc ) {
            if ( pos[1].first > 1 ) cnti++;
            for (int i = 2; i <= nc; i++)
              if ( pos[i - 1].first + 1 <= pos[i].first - 1 )
                cnti++;
            if ( pos[nc].first < n ) cnti++;
          } else cnti = 1;
          if ( cnti > 1 ) printf("0
    ");
          else printf("1
    ");
          continue;
        }
        if ( n == 1 ) {
          int cnti = 0;
          if ( nc ) {
            if ( pos[1].second > 1 ) cnti++;
            for (int i = 2; i <= nc; i++)
              if ( pos[i - 1].second + 1 <= pos[i].second - 1 )
                cnti++;
            if ( pos[nc].second < m ) cnti++;
          } else cnti = 1;
          if ( cnti > 1 ) printf("0
    ");
          else printf("1
    ");
          continue;
        }
        for (int i = 1, p, q; i <= nc; i++) {
          p = pos[i].first, q = pos[i].second;
          for (int k = 0; k < 9; k++) {
            int x = p + DIR[k][0], y = q + DIR[k][1];
            if ( 1 <= x && x <= n && 1 <= y && y <= m ) {
              // cerr << "build " << x << ' ' << y << endl;
              nod[++nnod].x = x, nod[nnod].y = y, nod[nnod].tag = k == 4;
            }
          }
        }
        //
        sort(nod + 1, nod + 1 + nnod);
        ntmp[0] = ntmp[1] = 0;
        if ( nod[1].x > 1 ) newTemp(), setTemp(1, m, false);
        int lasl = nod[1].x - 1;
        for (int i = 1; i <= nnod; i++) {
          if ( lasl < nod[i].x - 1 ) {
            newTemp(), setTemp(1, m, false);
            arrangeTemp();
          }
          newTemp();
          if ( nod[i].y > 1 ) setTemp(1, nod[i].y - 1, false);
          int toi = i; while ( toi < nnod && nod[toi + 1].x == nod[i].x ) toi++;
          for (int j = i; j <= toi; j++) {
            int toj = j; bool itag = nod[j].tag;
            while ( toj < toi && nod[toj + 1].y == nod[j].y )
              itag |= nod[++toj].tag;
            if ( !itag) setTemp(nod[j].y, nod[j].y, true);
            if ( toj < toi && nod[j].y + 1 < nod[toj + 1].y )
              setTemp(nod[j].y + 1, nod[toj + 1].y - 1, false);
            j = toj;
          }
          if ( nod[toi].y < m ) setTemp(nod[toi].y + 1, m, false);
          arrangeTemp();
          lasl = nod[i].x, i = toi;
        }
        if ( lasl < n ) {
          newTemp(), setTemp(1, m, false);
          arrangeTemp();
        }
        dfs(1);
        if ( ndfn < gr.np ) printf("0
    ");
        else if ( isans1 ) printf("1
    ");
        else printf("2
    ");
      }
      return 0;
    }
    
    点击展开/折叠 cyclic.cpp
    /*Lucky_Glass*/
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    typedef long long llong;
    #define con(typ) const typ &
    const int M = 1e6 + 10, HMOD = 1000793;
    
    int dv[200], prm[M], mu[M], summu[M];
    bool bok[M];
    int ndv, nprm;
    
    struct HashTable {
      int head[HMOD], nxt[M << 1], val[M << 1], key[M << 1];
      int ncnt;
      int& operator [] (con(int) _key) {
        for (int it = head[_key % HMOD]; it; it = nxt[it])
          if ( key[it] == _key )
            return val[it];
        int p = ++ncnt;
        key[p] = _key, nxt[p] = head[_key % HMOD], head[_key % HMOD] = p;
        return val[p] = 2e9;
      }
    } htab;
    
    void init(con(int) vk) {
      mu[1] = 1;
      for (int i = 2; i < M; ++i) {
        if ( !bok[i] ) mu[i] = -1, prm[++nprm] = i;
        for (int j = 1; j <= nprm && 1ll * prm[j] * i < M; ++j) {
          bok[i * prm[j]] = true;
          if ( i % prm[j] == 0 ) break;
          mu[i * prm[j]] = -mu[i];
        }
      }
      for (int i = 1; i < M; ++i) summu[i] = summu[i - 1] + mu[i];
      for (int i = 1; i <= vk; ++i)
        if ( vk % i == 0 && mu[i] )
          dv[++ndv] = i;
    }
    int funSum(con(int) n) {
      if ( n < M ) return summu[n];
      int &ret = htab[n];
      if ( ret != 2e9 ) return ret; 
      llong tmp = 1;
      for (int i = 2; i <= n; ++i) {
        int ii = n / (n / i);
        tmp -= (ii - i + 1ll)  * funSum(n / i);
        i = ii;
      }
      return ret = (int)tmp;
    }
    llong fun(con(int) n, con(int) m, con(int) vk) {
      if ( !n || !m ) return 0ll;
      llong ret = 0;
      if ( vk == 1 ) {
        int las = 0;
        for (int i = 1, li = std::min(n, m); i <= li; ++i) {
          int ii = std::min(n / (n / i), m / (m / i)), tmp = funSum(ii);
          ret += 1ll * (n / i) * (m / i) * (tmp - las);
          las = tmp;
          i = ii;
        }
        return ret;
      }
      if ( vk < ndv ) {
        for (int i = 1; i <= vk; ++i)
          if ( vk % i == 0 && mu[i] )
            ret += mu[i] * fun(m / i, n, i);
      } else {
        for (int i = 1; i <= ndv; ++i)
          if ( vk % dv[i] == 0 )
            ret += mu[dv[i]] * fun(m / dv[i], n, dv[i]);
      }
      return ret;
    }
    int main() {
      int n, m, vk;
      scanf("%d%d%d", &n, &m, &vk);
      init(vk);
      printf("%lld
    ", fun(n, m, vk));
      return 0;
    }
    

    THE END

    Thanks for reading!

    准备升空 到广阔云漠中
    日出穿透我安睡的眼眸
    整个世界 所有声音在视线上跳动
    尽情弹奏属于我的与众不同

    ——《世界不静默》 By 双笙

    > Link 世界不静默 - Bilibili

    欢迎转载٩(๑❛ᴗ❛๑)۶,请在转载文章末尾附上原博文网址~
  • 相关阅读:
    textarea回车在多浏览器兼容问题
    windows server平台移动oracle表空间
    奇妙的英文recreate,reproduce,regenerate也不同
    《Inside the C++ Object Model》笔记(1~7章)
    1.4买书问题C#源码
    C#的Compiler Error CS1660
    数学符号表
    C#工程添加了DLL编译运行时却提示”无法加载DLL“的解决方案
    看源代码那些事【转】
    救命的软件,查看你关掉的网站内容
  • 原文地址:https://www.cnblogs.com/LuckyGlass-blog/p/14782227.html
Copyright © 2011-2022 走看看