A. Alternative Accounts
题意:
现在有\(n\)个账号,举办\(k,k\leq 3\)场比赛。
现在每个人可能有多个账号,但每次只能用一个账号参加一场比赛。
现在给出\(k\)场比赛的参赛账号。
现在询问最少有多少人参加比赛。
思路:
分情况讨论即可。
我们可以直接认为\(k=3\)来分析:
- 若某个账号都出现在三场比赛中,那么直接让这个账号归属于某一人;
- 若某个账号出现在两场比赛中,那么这个账号可以和仅出现在另外一场比赛一次的账号进行匹配;不能匹配则不匹配;
- 若某个账号出现一次,现在剩下这些出现一次的账号可以互相匹配。
细节见代码,可能写得有点乱:
Code
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
const int MAXN = 1e5+5,MAXM = 1e6+5,MOD = 998244353,INF = 0x3f3f3f3f,N=2e5;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
const db eps = 1e-7;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define mid l + ((r-l)>>1)
#define pii pair<int,int>
#define vii vector<pii>
#define vi vector<int>
#define x first
#define y second
using namespace std;
int n,k,sta[MAXN],cnt[10];
int main(){
ios::sync_with_stdio(false);cin.tie(0);
cin>>n>>k;
for(int i=1;i<=k;i++){
int m,x;
cin>>m;
while(m--){
cin>>x;
sta[x] |= 1<<(i-1);
}
}
for(int i=1;i<=n;i++){
if(sta[i])cnt[sta[i]]++;
}
if(k==1){
cout<<cnt[1]<<'\n';
}else if(k==2){
cout << cnt[1] + cnt[2] + cnt[3] - min(cnt[1],cnt[2])<<'\n';
}else{
int ans=0;
for(int i=1;i<8;i++)ans+=cnt[i];
int tmp;
tmp = min(cnt[3], cnt[4]);
cnt[3] -= tmp;
cnt[4] -= tmp;
ans -= tmp;
tmp = min(cnt[5],cnt[2]);
cnt[5] -= tmp;
cnt[2] -= tmp;
ans -= tmp;
tmp = min(cnt[6],cnt[1]);
cnt[6] -= tmp;
cnt[1] -= tmp;
ans -= tmp;
tmp = min(min(cnt[1],cnt[2]),cnt[4]);
cnt[1] -= tmp;
cnt[2] -= tmp;
cnt[4] -= tmp;
ans -= 2*tmp;
tmp = min(cnt[1], cnt[2]);
cnt[1] -= tmp;
cnt[2] -= tmp;
ans -= tmp;
tmp = min(cnt[1],cnt[4]);
cnt[1] -= tmp;
cnt[4] -= tmp;
ans -= tmp;
tmp = min(cnt[2],cnt[4]);
cnt[2] -= tmp;
cnt[4] -= tmp;
ans -= tmp;
cout<<ans<<'\n';
}
return 0;
}
E. Matching Problem
题意:
给出两个序列\(a,b\),定义两个序列匹配当且仅当:
- 长度相等,且若\(a_i=a_j\),有\(b_i=b_j\)。
现在\(a\)的长度不超过\(300\),\(b\)的长度为\(4\)。问\(a\)有多少个子序列与\(b\)匹配。
思路:
直接暴力枚举子序列的前三个数,最后一个数直接预处理后缀即可。
Code
/*
* Author: heyuhhh
* Created Time: 2020/1/16 14:58:26
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 300 + 5;
int n;
int a[N];
int b[5], c[5];
int suf[N][N];
ll ans;
void gao(int pos, int cnt) {
if(pos >= n) return;
if(cnt == 3) {
int op = 0;
for(int i = 1; i <= 3; i++) {
if(b[4] == b[i]) op = i;
}
if(op == 0) {
ans += n - pos - suf[pos + 1][c[1]] - suf[pos + 1][c[2]] - suf[pos + 1][c[3]];
if(c[1] == c[2]) ans += suf[pos + 1][c[1]];
if(c[2] == c[3]) ans += suf[pos + 1][c[2]];
if(c[1] == c[3]) ans += suf[pos + 1][c[3]];
if(c[1] == c[2] && c[2] == c[3]) ans -= suf[pos + 1][c[1]];
} else {
ans += suf[pos + 1][c[op]];
}
return;
}
gao(pos + 1, cnt);
int x = a[pos + 1];
int ok = 1;
for(int i = 1; i <= cnt; i++) {
if((b[cnt + 1] == b[i]) != (x == c[i])) {
ok = 0;
}
}
if(ok) {
c[cnt + 1] = x;
gao(pos + 1, cnt + 1);
}
}
void run(){
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= 4; i++) cin >> b[i];
for(int i = n; i >= 1; i--) {
for(int j = 0; j < N; j++) suf[i][j] = suf[i + 1][j];
++suf[i][a[i]];
}
gao(0, 0);
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> n) run();
return 0;
}
G. Cryptographically Secure Pseudorandom Number Generator
题意:
给出一个素数\(p\),寻找所有的\(x\)满足:
\[ f(x)=min_{k=2}^{x}f(k) \]
\(f(x)\)满足\(x\cdot f(x)\equiv 1 (mod\ p)\)。
思路:
打个表发现具有对称关系。
然后猜一猜,可能只会枚举到根号,直接暴力过去就行了。。。
Code
/*
* Author: heyuhhh
* Created Time: 2020/1/16 21:33:24
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e6 + 5;
int MOD;
int inv[N];
void run(){
cin >> MOD;
inv[0] = inv[1] = 1;
vector <pii> ans;
int Min = INF;
for(int i = 2; i < MOD; i++) {
inv[i] = 1ll * (MOD - MOD / i) * inv[MOD % i] % MOD;
if(inv[i] <= Min) {
if(i > inv[i]) break;
Min = inv[i];
ans.push_back(MP(i, inv[i]));
}
}
vector <pii> res = ans;
reverse(all(res));
for(auto it : res) if(it.fi != it.se) ans.push_back(MP(it.se, it.fi));
cout << sz(ans) << '\n';
for(auto it : ans) cout << it.fi << ' ' << it.se << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
int T; cin >> T;
while(T--) run();
return 0;
}