多校聯訓2

2022-09-14 22:03:24 字數 4934 閱讀 3403

將前 \(n\) 個正整數,分成 \(m\) 個集合裡,(應該是按照第二類斯特林數的類別分的),然後乙個劃分是好的,當且僅當存在 \(m\) 的圓排列。然後求好的劃分的數量,

我們考慮乙個問題的轉化,我們乙個集合 \(a\) 可以向另乙個集合連邊 \(b\),當且僅當,\(\max(a)>\min(b)\),容易發現這樣的邊至少是單向的。

也就是說,如果我們把所有的這這些邊的圖畫出來,那麼這個圖一定是乙個強於競賽圖的圖。

我們要做的,就是求這個圖中的哈密頓迴路。競賽圖的一些性質 - _zwl - (cnblogs.com) 上面文章講了乙個競賽圖的性質。

那麼這個哈密頓迴路的條件等價於整個競賽圖是強連通的。考慮在我們上面得到的那個強於競賽圖的圖上,也是這樣的條件,因為這個圖的連通性肯定比競賽圖要強。如果這個玩意是強連通的,但是沒有一條哈密頓迴路,這明顯是不可能的,假設左邊是乙個強連通塊,右邊是乙個強連通塊,中間有乙個橋連線這個塊,我們總可以通過左邊連通塊的其他的邊去往右邊的塊,然後從橋回來。

那麼,我們直接計算這個圖的強連通情況的個數明顯是不好做的,我們在考慮問題的乙個轉化。

我們建立乙個下面的圖,先將數字從小到大排列,然後大的數字向小的數字連邊,然後同一集合的數字向集合中的最大數字連邊。

不難發現這個圖的連通性和上面那個圖是相等的。

那麼我們按照順序dp下面這個圖的即可。

我們設計狀態為 \(f[i][j][k]\) 表示從後向前 \(\text\) 到了第 \(i\) 個數字,已經有了 \(j\) 個集合,然後我們從 \(i\) 這個數字開始到後面一共連續有 \(k\) 個集合沒有跟最後乙個集合相連(不考慮這些集合的聯通狀態)。最初狀態是 \(f[n][1][1]=1\)

那麼我們可以分下面幾個情況轉移 \(i\rightarrow i-1\):

最後的答案就是 \(f[1][m][0]\)。

我們注意到這個解法的空間是 \(o(n^3)\),而時間也是 \(o(n^3)\),我們可以通過滾動陣列把空間優化到 \(o(n^2)\)。

這是我和武漢外國語學校的熊子豪討論的求解第一題的乙個可能可行的方法,但是由於知識所限,不能完成演算法的最後部分,因為沒有學習二元多項式相關理論。

考慮化用題解中的性質:不能將值域劃分成兩部分。

如果去掉這個條件,答案顯然是 \(\displaystyle \);加上來,考慮容斥原理。令 \(f(i)\) 表示欽定了值域被劃分為個 \(i\) 部分的方案數。所求即為:

\[ans=\sum _^n (-1)^ f(i)

\]考慮求解這個 \(f(k)\),最暴力的想法是列舉值域的乙個劃分 \(\\),其中 \(\sum i = n\)。然後再列舉分成的集合數量,分別是 \(j_1,j_2,\dots,j_k\),且 \(\sum j = m\)。這樣的一種劃分,對應的方案數是 \(\displaystyle\prod _^k \)。化一下上面的式子:

\[\begin

ans &= -\sum _^n (-1)^k f(k)\\

&= -\sum_^n \sum_ \sum_ \prod_^k -

\end

\]下面可能需要一些二元多項式求逆之類的高階東西,這我就不太會了。

// 這是我的解法的**

#include using std::cin;

using std::cout;

const int maxn = 505, mod = 998244353;

/*問題轉化

強連通圖

f[i][j][k] 為從後向前做到 i 個, 然後已經有 j 個集合,有 k 個集合沒有跟 $n$ 那個相連

那麼 最後的答案就是 f[1][m][0]

*/int n, m, f[2][maxn][maxn];

auto mod = (int x)

else if (x < 0)

else

};int main()

f[n & 1][1][0] = 1;

for (int i = n - 1; i; --i)

} // 連向之前的乙個集合和 最後乙個集合相連的

for (int j = 1; j <= m && j < num; ++j)

// 連向之前的 j - k 個集合均可

} // 和之前乙個集合不和最後乙個集合相連的相連

for (int j = 1; j < num; ++j)

} }cout << f[1][m][0] << '\n';

return 0;

}

設 \(1\sim n\) 中與 \(n\) 互質的數字數量為 \(\varphi (n)\),然後給定乙個 \(n\) 個正整數序列 \(a\),一次執行 \(q\) 個操作,操作有三種型別。

0 pos x修改 \(a_\) 位置的值為 \(x\)。

1 l r查詢 \(\varphi (\sum_^r a_i)\)

2 l r查詢 \(\varphi (\prod _^r a_i)\)

\(n\le 5 \times 10^4\),\(q\le 1\times 10^5\),\(a_i\le 4\times 10^4\) 資料完全隨機。

我們考慮,由於資料隨機,所以可以寫一些複雜度看起來完全不對的演算法,但是他在資料隨機的時候保證複雜度即可。

我們考慮直接用線段樹維護這個序列,然後維護區間和和區間乘法即可。

我們對於一操作的答案,由於值域不大,答案最大是 \(2e9\) 級別的,我們可以每次 \(o(\sqrt)\) 的求出來他的 \(\varphi\) 值即可。

這樣每次的複雜度為 \(o(\log n+\sqrt )\)

我們在考慮二操作,這玩意答案明顯很大,但是我們由於 \(\varphi\) 的計算可以知道,我們只要找到他的每個質因數 \(x\),然後乘上 \(\frac\) 即可。

於是我們考慮,可以在每個線段樹節點上維護乙個bitset每一位表示有沒有第 \(i\) 個質因數即可。

由於資料隨機,這樣做是很快的。我們可以得到 \(4\times 10^4\) 內的質因數數量一共為 \(4203\) 個,不多。

所以只要按照上面這樣做即可。

#pragma gcc optimize("ofast")

#include const int maxv = 40005, mod = 1e9 + 7, maxn = 5e4 + 10;

using std::bitset;

int pri[maxv], vis[maxv], idx[maxv], inv[maxv], p[maxv];

bitset<4210> factor[maxv], ans;

int n, m, a[maxn], sc[maxn];

void print(int x)

print(x / 10);

putchar(x % 10 + 48);

}int read()

while (isdigit(ch))

return x;

}struct node nd[maxn * 4];

#define jy(i) nd[i].jy

#define mul(i) nd[i].mul

inline int ls(int k)

inline int rs(int k)

inline void up(int k)

void build(int k, int l, int r)

int mid = (l + r) / 2;

build(ls(k), l, mid);

build(rs(k), mid + 1, r);

up(k);

}auto ksm = (int x, int y) -> int

} return ret;

};void modify(int k, int l, int r, int pos)

int mid = (l + r) / 2;

if (pos <= mid)

else

up(k);

}long long query2(int k, int l, int r, int ql, int qr)

int mid = (l + r) / 2;

long long ret = 1;

if (ql <= mid)

if (mid < qr)

return ret;

}void add(int x, int y)

}int query1(int r)

return ret;

}int main()

for (int j = 1; j <= pri[0] && pri[j] * i < maxv; ++j)

} }inv[0] = inv[1] = 1;

for (int i = 2; i < maxv; ++i)

for (int i = 1; i <= pri[0]; ++i)

for (int i = 1; i < maxv; ++i)

} if (x != 1)

} //

n = read();

m = read();

for (int i = 1; i <= n; ++i)

build(1, 1, n);

for (int opt, l, r; m--; )

else if (opt == 1) }}

if (k > 1)

print(ret);

putchar('\n');

} else

print(ret);

putchar('\n');

} }return 0;

}

實際實現的時候,由於可能有點卡常,可以考慮把求和的線段樹換成樹狀陣列。

P3467 2015多校聯訓1 統計

時間限制 20000 ms 空間限制 165536 kb 問題描述 現在有乙個陣列 a,陣列中有 n 個元素。定義乙個函式 f l,r 表示 i l i r 的 個數,其中 i 符合條件 不存在 j l j r 且 j i 滿足 ai mod aj 0 求 i 1n j inf i,j mod 10...

NKOJ3485 2015多校聯訓4 資料

問題描述 mr h 出了一道資訊學競賽題,就是給 n 個數排序。輸入格式是這樣的 試題有若干組資料。每組資料的第乙個是乙個整數 n,表示總共有 n 個數待排序 接下來 n 個整數,分別表示這n 個待排序的數。例如 3 4 2 1 4 1 2 3 4,就表示有兩組資料。第一組有3 個數 4,2,1 第...

P3500 2015多校聯訓6 獨立集 dp

題目大意 求一數列的最大上公升子串行 必定存在此最大上公升子串行的點 如果乙個點必定存在與最長上公升子串行中,那麼必須滿足兩個條件 1.該點存在於最長上公升子串行中。2.通過此點的最長上公升子串行長度唯一。但此題由於資料範圍為1000005,所以常規n方求最長上公升子串行的方法肯定不行,那麼就考慮用...