2018 ccpc final
2018 CCPC FINAL
kunkun全球后援队训练赛赛
A.
签到
笨比mwh wa了两发
#include <stdio.h> #include <iostream> #include <cstring> #include <algorithm> #include <cmath> #pragma GCC optimize(2) using namespace std; typedef long long ll; const int N = 1e5 + 5; int t, n, m, kas; struct node{ int d, t; }list[N]; bool cmp(node a, node b){ if (a.d == b.d) return a.t < b.t; return a.d < b.d; } int main() { // cin.tie(0); // cout.tie(0); // ios::sync_with_stdio(0); cin >> t; kas = 0; while (t--) { cin >> n >> m; for (int i = 0; i < n; ++i) cin >> list[i].d; for (int i = 0; i < n; ++i) cin >> list[i].t; sort(list, list + n, cmp); int ans = 0; int x = 0; for (int i = 0; i < n; ++i) { x += list[i].t; if (x <= m) ans++; else break; } printf("Case %d: %d\n", ++kas, ans); } }
L
数学 思维
看了样例,一开始的想法是把这个数字先除以6,然后再找。(当然找不到了)
然后发现题目给了条件
A weaker version of this conjecture states that every odd number greater than 5 is the sum of three prime numbers.
顺其自然的就想到解法
先找到比n小且和n的差大于等于11的最大素数tmp (tmp就是要找的6个素数中的一个), 得到 n - tmp , 如果 n - tmp 是奇数, 就把它减去4, 输出 2 2,如果 n - tmp 是偶数, 就把它减去5, 输出 2 3。由于题目给出的结论, 剩下的数是肯定可以由3个素数组成的。因为我们之前减的tmp是最大的满足条件的素数,所以剩余的素数应该非常小,可以直接暴力。
#include <stdio.h> #include <iostream> #include <cstring> #include <algorithm> #include <cmath> #define REP(i,k,n) for(int i=k;i<=n;i++) #pragma GCC optimize(2) using namespace std; typedef long long ll; int t, ind; ll n; const int N = 1e5 + 5; int prime[10000010],book[10000010]; void turn(int p) { for(int i = 2; i <= p; i++) { if(!book[i]) prime[++ind]=i;//如果没有筛过,记录素数 REP(j,1,ind){//其中记录数组里的素数保证严格递增 if(i*prime[j]>p) break;//保证小于n,要不然没有意义 book[i*prime[j]]=1;//筛去这个合数 if(!i%prime[j]) break;//如果>=这个数的最小质因子,那就结束 } } } bool check(ll n){ ll tmp = sqrt(n); for (int i = 2; i <= tmp; ++i) if (n % i == 0) return false; return true; } int main() { turn(100000); cin >> t; int kas = 0; while (t--) { scanf("%lld", &n); if (n == 12) { printf("Case %d: 2 2 2 2 2 2\n", ++kas); continue; } ll tmp; if (n <= 11) { printf("Case %d: IMPOSSIBLE\n", ++kas); continue; } for (ll i = n - 11; i >= 0; --i) { if (check(i)) { tmp = i; break; } } n = n - tmp; int flag; if (n & 1) { n -= 4; flag = 1; } else { n -= 5; flag = 2; } for (ll i = 1; i <= 9592; ++i) { for (ll j = 1; j <= 9592; ++j) { if (check(n - prime[i] - prime[j]) && n - prime[i] - prime[j] > 0) { if (flag == 1) { printf("Case %d: 2 2 %lld %d %d %d\n", ++kas, tmp, prime[i], prime[j], n - prime[i] - prime[j]); flag = -1; break; } else { printf("Case %d: 2 3 %lld %d %d %d\n", ++kas, tmp, prime[i], prime[j], n - prime[i] - prime[j]); flag = -1; break; } } } if (flag == -1) break; } } }
G
找规律 逆元
直接dfs搜
打表程序找出规律,推出公式,注意mod的时候要逆元
#include <cstdio> #include <cmath> #include <algorithm> typedef long long ll; const ll mod = 1e9+7; using namespace std; ll t, m, n; ll solve(ll n) { return n * (n + 1) / 2; } ll quick_m(ll a, ll x) { ll ans =1; while (x) { if (x&1) { ans = ans * a % mod; } x>>=1; a = a * a % mod; } return ans; } int main () { scanf("%d", &t); int kas = 0; while (t--) { scanf("%lld%lld", &n, &m); if (n < 3 || m < 3) { printf("Case %d: %d\n", ++kas, 0); continue; } else if (m == 3 && n == 3) { printf("Case %d: %d\n", ++kas, 1); continue; } else if (n > 7 && m > 7) { ll ans = 1; // n--; // m--; ans = ans * m % mod; ans = ans * (m-1) % mod; ans = ans * (m-2) % mod; ans = ans * (m+1) % mod; // ans = ans * a[n] % mod; ans = ans * quick_m(24, mod-2) % mod; ans = ans * n % mod; ans = ans * (n-1) % mod; ans = ans * (n-2) % mod; ans = ans * (n+1) % mod; // ans = ans * a[m] % mod; ans = ans * quick_m(24, mod-2) % mod; printf("Case %d: %lld\n", ++kas, ans); } else { n -= 2; m -= 2; ll ans1 = 0, ans2 = 0; for (ll i = 1; i <= n; i++) { ans1 = (ans1 + solve(i) * (n-i+1)) % mod; } for (ll j = 1; j <= m; j++) { ans2 = (ans2 + solve(j) * (m-j+1)) % mod; } printf("Case %d: %lld\n", ++kas, ans1*ans2 % mod); } } return 0; }
正解
题目意思可以理解为寻找i两个子矩阵,推出公式 ()
https://blog.csdn.net/Tony5t4rk/article/details/88054604?tdsourcetag=s_pctim_aiomsg
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5 + 5; const int mod = 1e9 + 7; ll C[maxn][5]; void Init() { C[0][0] = 1; for (int i = 1; i < maxn; ++i) { C[i][0] = 1; for (int j = 1; j < 5; ++j) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); Init(); int t; cin >> t; for (int Case = 1; Case <= t; ++Case) { int n, m; cin >> n >> m; if (n < 3 || m < 3) { cout << "Case " << Case << ": " << 0 << endl; continue; } cout << "Case " << Case << ": " << ((C[n][3] + C[n][4]) % mod) * ((C[m][3] + C[m][4]) % mod) % mod << endl; } return 0; }
L
没打出来
等待补提,贴一个隔壁队大神的代码
//zyh #include <stdio.h> #include <algorithm> #include <vector> #include <set> #include <cstring> using namespace std; typedef long long ll; const int N = 1e5+10; int numx[N], numy[N], connumy[N], connumx[N]; vector <int> vex, vey; set <int> st[N]; struct node{ int x, y; }a[N]; int newyid[N], newxid[N]; bool cmpy(int x, int y) { return numy[x] > numy[y]; } bool cmpx(int x, int y) { return numx[x] > numx[y]; } set <int> :: iterator it; int main() { // freopen("1.txt", "r", stdin); int T, n, ca=0, x, y; scanf("%d", &T); while(T--) { memset(numx, 0, sizeof(numx)); memset(numy, 0, sizeof(numy)); memset(connumy, 0, sizeof(connumy)); memset(connumx, 0, sizeof(connumx)); scanf("%d", &n); for(int i = 1; i <= n; i++) st[i].clear(); vex.clear(); vey.clear(); for(int i = 1; i <= n; i++) { scanf("%d %d", &a[i].x, &a[i].y); vex.push_back(a[i].x); vey.push_back(a[i].y); } sort(vex.begin(), vex.end()); vex.erase(unique(vex.begin(), vex.end()), vex.end()); sort(vey.begin(), vey.end()); vey.erase(unique(vey.begin(), vey.end()), vey.end()); for(int i = 1; i <= n; i++) { x = lower_bound(vex.begin(), vex.end(), a[i].x)-vex.begin()+1; y = lower_bound(vey.begin(), vey.end(), a[i].y)-vey.begin()+1; numx[x]++; connumx[x]++; numy[y]++; connumy[y]++; st[x].insert(y); } int sizey = vey.size(), sizex = vex.size(); for(int i = 1; i <= sizey; i++) newyid[i] = i; for(int i = 1; i <= sizex; i++) newxid[i] = i; sort(newyid+1, newyid+1+sizey, cmpy); sort(newxid+1, newxid+1+sizex, cmpx); sort(numx+1, numx+1+sizex, greater<int>()); sort(numy+1, numy+1+sizey, greater<int>()); ll res = 0, num = 0; for(int i = 1; i <= sizex; i++) { if(numx[i]+numy[1] <= res) continue; for(int j = 1; j <= sizey; j++) { int tmp = st[newxid[i]].count(newyid[j]); if(numx[i]+numy[j]-tmp>res) res = numx[i]+numy[j]-tmp; if(tmp == 0) break; } } for(int i = 1; i <= n; i++) { x = lower_bound(vex.begin(), vex.end(), a[i].x)-vex.begin()+1; y = lower_bound(vey.begin(), vey.end(), a[i].y)-vey.begin()+1; if(connumx[x]+connumy[y]==res+1) num++; } for(int i = 1; i <= sizex; i++) { int s = lower_bound(numy+1, numy+1+sizey, res-numx[i], greater<int>()) - numy; int e = upper_bound(numy+1, numy+1+sizey, res-numx[i], greater<int>()) - numy - 1; int tmp = e - s + 1; for(it = st[newxid[i]].begin(); it != st[newxid[i]].end(); it++) { if(connumy[*it]==res-numx[i]) tmp--; } num += tmp; } if(res==2) num /= 2; printf("Case %d: %lld %lld\n", ++ca, res, num); } }
膜yh大神 ORZ