[Codeforces] combinatorics (R1200) Part.2

[Codeforces] combinatorics (R1200) Part.2

题单:https://codeforces.com/problemset?tags=combinatorics,0-1200

1543B. Customising the Track

原题指路:https://codeforces.com/problemset/problem/1543/B

题意

给定一个长度为 n n n的序列 a 1 , ⋯   , a n a_1,\cdots,a_n a1,,an.现有操作:选择两个下标 i , j    ( 1 ≤ i , j ≤ n , i ≠ j ) i,j\ \ (1\leq i,j\leq n,i\neq j) i,j  (1i,jn,i=j),令 a i − − , a j + + a_i--,a_j++ ai,aj++.求经过若干次(可能为 0 0 0次)操作后 ∑ i = 1 n ∑ j = i + 1 n ∣ a i − a j ∣ \displaystyle\sum_{i=1}^n \sum_{j=i+1}^n |a_i-a_j| i=1nj=i+1naiaj的最小值.

t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据第一行输入一个整数 n    ( 1 ≤ n ≤ 2 e 5 ) n\ \ (1\leq n\leq 2\mathrm{e}5) n  (1n2e5).第二行输入 n n n个整数 a 1 , ⋯   , a n    ( 0 ≤ a i ≤ 1 e 9 ) a_1,\cdots,a_n\ \ (0\leq a_i\leq 1\mathrm{e}9) a1,,an  (0ai1e9).数据保证所有测试数据的 n n n之和不超过 2 e 5 2\mathrm{e}5 2e5.

思路

a n s = ∑ i = 1 n ∑ j = i + 1 n ∣ a i − a j ∣ \displaystyle ans=\sum_{i=1}^n \sum_{j=i+1}^n |a_i-a_j| ans=i=1nj=i+1naiaj描述序列 a [ ] a[] a[]的波动情况,欲使其最小,应尽量让 a [ ] a[] a[]均匀分布.设 a [ ] a[] a[]中元素之和为 s u m sum sum,则 n n n个元素每个先分 ⌊ s u m n ⌋ \left\lfloor\dfrac{sum}{n}\right\rfloor nsum,这一部分不会对 a n s ans ans有贡献.剩下的 s u m % n sum\% n sum%n放在前 s u m % n sum\% n sum%n个元素上,此时前 s u m % n sum\% n sum%n个为 1 1 1的元素会与后面的 ( n − s u m % n ) (n-sum\% n) (nsum%n)个为 0 0 0的元素每对产生 1 1 1点贡献,故 a n s = ( s u m % n ) ( n − s u m % n ) ans=(sum\% n)(n-sum\% n) ans=(sum%n)(nsum%n).

代码

void solve() {
	int n; cin >> n;
    ll sum = 0;
    for (int i = 0; i < n; i++) {
        int a; cin >> a;
        sum += a;
    }

    cout << (ll)(sum % n) * (n - sum % n) << endl;
} 

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1574B. Combinatorics Homework

原题指路:https://codeforces.com/problemset/problem/1574/B

题意 ( 2   s 2\ \mathrm{s} 2 s)

给定四个整数 a , b , c , m a,b,c,m a,b,c,m,判断是否存在满足下列条件的字符串:①包含 a a a个字符’A’, b b b个字符’B’, c c c个字符’C’;②不存在其他字符;③有恰好 m m m对相邻相同的字符,若存在则输出"YES";否则输出"NO".

t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据输入四个整数 a , b , c , m    ( 1 ≤ a , b , c ≤ 1 e 8 , 0 ≤ m ≤ 1 e 8 ) a,b,c,m\ \ (1\leq a,b,c\leq 1\mathrm{e}8,0\leq m\leq 1\mathrm{e}8) a,b,c,m  (1a,b,c1e8,0m1e8).

思路

考虑对给定的 a , b , c a,b,c a,b,c,求合法的 m m m的范围.

①最大值:显然将所有’A’、‘B’、'C’分别放一起时取得最大值,此时 m = ( a − 1 ) + ( b − 1 ) + ( c − 1 ) = a + b + c − 3 m=(a-1)+(b-1)+(c-1)=a+b+c-3 m=(a1)+(b1)+(c1)=a+b+c3.

②最小值:因字符’A’、‘B’、'C’地位等价,不妨设 a ≤ b ≤ c a\leq b\leq c abc.

​ 考虑构造"CACACA…CBCBCB…CCC…"的字符串,即用 ( a + b ) (a+b) (a+b)个字符’C’隔开相邻的’A’和’B’,

​ 此时剩下的 c − ( a + b ) c-(a+b) c(a+b)个字符’C’会组成 ( c − a − b − 1 ) (c-a-b-1) (cab1)对相邻相同的字符.

综上, m ∈ [ c − a − b − 1 , a + b + c − 3 ] m\in[c-a-b-1,a+b+c-3] m[cab1,a+b+c3].

m m m可取到 [ c − a − b − 1 , a + b + c − 3 ] [c-a-b-1,a+b+c-3] [cab1,a+b+c3]中的任意整数.

[] 当 m > 0 m>0 m>0时,取走一个出现次数最多的字符,并使得 m − − m-- m,直至 m = 0 m=0 m=0.

考虑将取走的字符放回 m = 0 m=0 m=0的字符串中对应字符最后一次出现的位置之后,

​ 显然这样使得该字符的出现次数 + + ++ ++,同时 m + + m++ m++.

代码

void solve() {
	int tmpa, tmpb, tmpc, m; cin >> tmpa >> tmpb >> tmpc >> m;

   int a = min({tmpa, tmpb, tmpc}), c = max({tmpa, tmpb, tmpc}), b = tmpa + tmpb + tmpc - a - c;
   int low = c - a - b - 1, high = a + b + c - 3;
   cout << (low <= m && m <= high ? "YES" : "NO") << endl;
} 

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1581A. CQXYM Count Permutations

原题指路:https://codeforces.com/problemset/problem/1581/A

题意

求满足如下条件的长度为 2 n 2n 2n 1 ∼ 2 n 1\sim 2n 12n的排列的个数,答案对 1 e 9 + 7 1\mathrm{e}9+7 1e9+7取模:满足 p i < p i + 1 p_i<p_{i+1} pi<pi+1的下标 i i i的个数不少于 n n n.

t t t组测试数据.每组测试数据输入一个整数 n    ( 1 ≤ n ≤ 1 e 5 ) n\ \ (1\leq n\leq 1\mathrm{e}5) n  (1n1e5).数据保证所有测试数据的 n n n之和不超过 1 e 5 1\mathrm{e}5 1e5.

思路

称一个排列的值为满足 p i < p i + 1 p_i<p_{i+1} pi<pi+1的下标 i i i的个数.将一个值为 i i i的排列倒序可得值为 ( 2 n − i ) (2n-i) (2ni)的排列,则所有值 < n <n <n的排列构成的集合与所有值 ≤ n \leq n n的排列构成的集合间存在双射,则答案为每个集合的大小,即 a n s = 1 2 ⋅ ( 2 n ) ! ans=\dfrac{1}{2}\cdot (2n)! ans=21(2n)!.

代码

const int MAXN = 2e5 + 5;
const int MOD = 1e9 + 7;
int fac[MAXN], ifac[MAXN];

void init() {
  fac[0] = 1;
  for (int i = 1; i < MAXN; i++) fac[i] = (ll)fac[i - 1] * i % MOD;
  ifac[MAXN - 1] = qpow(fac[MAXN - 1], MOD - 2, MOD);
  for (int i = MAXN - 1; i; i--) ifac[i - 1] = (ll)ifac[i] * i % MOD;
}

void solve() {
	init();

  CaseT {
    int n; cin >> n;
    cout << (ll)fac[2 * n] * qpow(2, MOD - 2, MOD) % MOD << endl;
  }
} 

int main() {
	solve();
}


1582B. Luntik and Subsequences

原题指路:https://codeforces.com/problemset/problem/1582/B

题意

给定一个长度为 n n n的序列 a 1 , ⋯   , a n a_1,\cdots,a_n a1,,an,令 s = ∑ i = 1 n a i \displaystyle s=\sum_{i=1}^n a_i s=i=1nai.称 a [ ] a[] a[]的一个非空子列是好的,如果其中的元素之和为 s − 1 s-1 s1,求 a [ ] a[] a[]的非空子列中好的子列的个数.

t    ( 1 ≤ t ≤ 1000 ) t\ \ (1\leq t\leq 1000) t  (1t1000)组测试数据.每组测试数据第一行输入一个整数 n    ( 1 ≤ n ≤ 60 ) n\ \ (1\leq n\leq 60) n  (1n60).第二行输入 n n n个整数 a 1 , ⋯   , a n    ( 0 ≤ a i ≤ 1 e 9 ) a_1,\cdots,a_n\ \ (0\leq a_i\leq 1\mathrm{e}9) a1,,an  (0ai1e9).

思路

先不考虑 a [ ] a[] a[]中值为 0 0 0的元素,显然一个子列是好的当且仅当它是 a [ ] a[] a[]删除一个值为 1 1 1的元素得到的子列,而值为 0 0 0的元素可删可不删,设值为 0 0 0 1 1 1的元素的个数分别为 c n t 0 cnt_0 cnt0 c n t 1 cnt_1 cnt1,则 a n s = c n t 1 ⋅ 2 c n t 0 ans=cnt_1\cdot 2^{cnt_0} ans=cnt12cnt0.

代码

void solve() {
	int n; cin >> n;
  int cnt0 = 0, cnt1 = 0;
  vi a(n);
  for (auto& ai : a) {
    cin >> ai;
    cnt0 += ai == 0, cnt1 += ai == 1;
  }

  cout << (ll)cnt1 * ((ll)1 << cnt0) << endl;
} 

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1658B. Marin and Anti-coprime Permutation

原题指路:https://codeforces.com/problemset/problem/1658/B

题意

定义一个长度为 n n n的排列 p 1 , ⋯   , p n p_1,\cdots,p_n p1,,pn是好的,如果 gcd ⁡ ( 1 ⋅ p 1 , 2 ⋅ p 2 , ⋯   , n ⋅ p n ) > 1 \gcd(1\cdot p_1,2\cdot p_2,\cdots,n\cdot p_n)>1 gcd(1p1,2p2,,npn)>1.求 1 ∼ n 1\sim n 1n的排列中好的排列的个数,答案对 998244353 998244353 998244353取模.

t    ( 1 ≤ t ≤ 1000 ) t\ \ (1\leq t\leq 1000) t  (1t1000)组测试数据.每组测试数据输入一个 n    ( 1 ≤ n ≤ 1000 ) n\ \ (1\leq n\leq 1000) n  (1n1000).

思路

g = gcd ⁡ ( 1 ⋅ p 1 , 2 ⋅ p 2 , ⋯   , n ⋅ p n ) g=\gcd(1\cdot p_1,2\cdot p_2,\cdots,n\cdot p_n) g=gcd(1p1,2p2,,npn),则 g ≤ 2 g\leq 2 g2.

[] ① g > 2 g>2 g>2时,若 ∃ \exists 素数 p > 2   s . t .   p ∣ g p>2\ s.t.\ p\mid g p>2 s.t. pg,因 1 ∼ n 1\sim n 1n中有 ⌊ n p ⌋ \left\lfloor\dfrac{n}{p}\right\rfloor pn p p p的倍数,则至多能匹配 2 ⌊ n p ⌋ < n 2\left\lfloor\dfrac{n}{p}\right\rfloor<n 2pn<n个数.

g ≤ 2 g\leq 2 g2时,可将值为奇数的数放在偶数下标的位置,将值为偶数的数放在奇数下标的位置. 1 ∼ n 1\sim n 1n中有 n 2 \dfrac{n}{2} 2n个奇数和 n 2 \dfrac{n}{2} 2n个偶数,故 a n s = [ ( n 2 ) ! ] 2 ans=\left[\left(\dfrac{n}{2}\right)!\right]^2 ans=[(2n)!]2.

代码

const int MAXN = 1005;
const int MOD = 998244353;
int fac[MAXN], ifac[MAXN];

void init() {
  fac[0] = 1;
  for (int i = 1; i < MAXN; i++) fac[i] = (ll)fac[i - 1] * i % MOD;
  ifac[MAXN - 1] = qpow(fac[MAXN - 1], MOD - 2, MOD);
  for (int i = MAXN - 1; i; i--) ifac[i - 1] = (ll)ifac[i] * i % MOD;
}

void solve() {
	init();

  CaseT {
    int n; cin >> n;
    cout << (n & 1 ? 0 : (ll)fac[n / 2] * fac[n / 2] % MOD) << endl;
  }
} 

int main() {
	solve();
}


1674B. Dictionary

原题指路:https://codeforces.com/problemset/problem/1674/B

题意 ( 2   s ) (2\ \mathrm{s}) (2 s)

将两相异的小写英文字母组成一个单词,将所有单词按字典序排序,下标从 1 1 1开始.给定一个单词,求其下标.

t    ( 1 ≤ t ≤ 650 ) t\ \ (1\leq t\leq 650) t  (1t650)组测试数据.每组测试数据输入一个长度为 2 2 2的、只包含两相异的小写英文字母的单词.

思路

预处理出所有单词即可.

代码

umap<string, int> mp;

void init() {
  for (char fi = 'a'; fi <= 'z'; fi++) {
    for (char se = 'a'; se <= 'z'; se++) {
      if (fi == se) continue;

      string word(2, ' ');
      word[0] = fi, word[1] = se;
      mp[word] = mp.size() + 1;
    }
  }
}

void solve() {
	init();

  CaseT{
    string s; cin >> s;
    cout << mp[s] << endl;
  }
} 

int main() {
	solve();
}


1674C. Infinite Replacement

原题指路:https://codeforces.com/problemset/problem/1674/C

题意 ( 2   s 2\ \mathrm{s} 2 s)

给定一个只包含字符’a’的字符串 s s s和只包含小写英文字母的字符串 t t t.现有操作:将 s s s中的一个字符’a’替换为字符串 t t t.求若干次(含零次)操作后能得到的不同字符串的数量.

t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据第一行输入长度不超过 50 50 50的只包含字符’a’的字符串 s s s.第二行输入长度不超过 50 50 50的只包含小写英文字母的字符串 t t t.

对每组测试数据,若能得到无穷多种的不同字符串,输出 − 1 -1 1;否则输出能得到的不同字符串的数量.

思路

①若 t t t为"a",则操作后不改变原串, a n s = 1 ans=1 ans=1.

②若 t t t的长度 ≥ 2 \geq 2 2且包含字符’a’,则每次操作后 s s s中’a’的数量不减, a n s = I N F ans=INF ans=INF.

③若 t t t的长度 ≥ 2 \geq 2 2且不包含字符’a’,则每次操作后 s s s中’a’的数量 − 1 -1 1.

s s s中每个字符’a’都可选择替换或不替换, a n s = 2 l e n ans=2^{len} ans=2len,其中 l e n len len s s s的长度.

代码

void solve() {
	string s, t; cin >> s >> t;

  if (t == "a") cout << 1 << endl;
  else {
    bool ok = false;
    for (auto ch : t) ok |= ch == 'a';

    if (ok) cout << -1 << endl;
    else cout << ((ll)1 << s.length()) << endl;
  }
} 

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


截至2022.09.14,无新题目

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值