文章目录

  • 上海理工大学第二届“联想杯”全国程序设计邀请赛
    • A.A-SOUL!
    • B.Bheith i ngra le
    • C.Counting Cats!
    • D.Dahno Dahno
    • E.Experiment Class
    • I.Identical Day
    • J.JXC&Jesus
    • K.Kazusa’s Party
    • L.Little Witch Academia
    • M.Minecraft

上海理工大学第二届“联想杯”全国程序设计邀请赛

A.A-SOUL!

题意:

题解:

代码:

#include <bits/stdc++.h>#define int long long
#define debug(x) cout << #x << " = " << x << endl;
using namespace std;int const MAXN = 2e5 + 10;
int n, m, T, a[MAXN];
unordered_map<int, int> mp;signed main() {ios_base::sync_with_stdio(false);cin.tie(NULL);cin >> n >> m;for (int i = 1; i <= n; ++i) cin >> a[i];sort(a + 1, a + 1 + n);n = unique(a + 1, a + 1 + n) - a - 1;int res = 0;for (int i = 1; i <= n; ++i) {mp[a[i]] = mp[a[i] - m] + 1;res = max(res, mp[a[i]]);}cout << res;return 0;
}

B.Bheith i ngra le

题意: 给定n * m的网格,对于每一个水平位置i,都有个高度hi。定义“山”为:存在l和r,使得1∼l−11 \sim l-11∼l−1,都有hi<=hi+1hi<=h_{i+1}hi<=hi+1​;对于l∼rl\sim rl∼r,都有 hi=hi+1hi=h_{i+1}hi=hi+1​;对于 r+1∼nr+1\sim nr+1∼n,都有 hi>=hi+1hi >= h_{i+1}hi>=hi+1​。问:给定n和m,求有多少种构成“山”的方案数。1<=n,m<=2000,hi>=01<=n,m<=2000,hi>=01<=n,m<=2000,hi>=0

题解: 组合计数–隔板法。考虑枚举l和r,然后枚举这段区间内的hi。那么得到式子:

∑i=1n∑j=in∑k=1mCi+k−2k−1∗Cn−j+k−1k−1\sum_{i=1}^n\sum_{j=i}^n\sum_{k=1}^m C_{i+k-2}^{k-1}*C_{n-j+k-1}^{k-1}∑i=1n​∑j=in​∑k=1m​Ci+k−2k−1​∗Cn−j+k−1k−1​

解释下这个式子,对于前i-1个位置,要满足hi<=hi+1h_i<=h_{i+1}hi​<=hi+1​。然后可以选择的高度范围为0∼k−10\sim k-10∼k−1,那么就是在0∼k−10 \sim k-10∼k−1 这k个数字中,选择出 i−1i-1i−1 个数字的方案数。记aia_iai​表示选择数字i的次数,那么问题等价于求解方程 a0+a1+...+ak−1=i−1,ai>=0a_0+a_1+...+a_{k-1}=i-1,\ a_i>=0a0​+a1​+...+ak−1​=i−1, ai​>=0 的解数目。

因为ai>=0a_i>=0ai​>=0,那么按照隔板法往k-1个容器内部加入1个物品,那么就是k−1+i−1=k+i−2k-1+i-1=k+i-2k−1+i−1=k+i−2个物品放入k个箱子里,每个箱子至少一个,即C(k+i-2, k -1)。

如果直接解上面的式子,就是O(n3)O(n^3)O(n3)

由于第一个式子和j没关系,第二个式子和i没关系,那么式子变化为:

∑i=1n∑k=1mCi+k−2k−1∗∑j=inCn−j+k−1k−1\sum_{i=1}^n\sum_{k=1}^m C_{i+k-2}^{k-1}*\sum_{j=i}^nC_{n-j+k-1}^{k-1}∑i=1n​∑k=1m​Ci+k−2k−1​∗∑j=in​Cn−j+k−1k−1​

这里记∑j=inCn−j+k−1k−1\sum_{j=i}^nC_{n-j+k-1}^{k-1}∑j=in​Cn−j+k−1k−1​ 为 num[i][k]num[i][k]num[i][k]

那么式子转换为:∑i=1n∑k=1mCi+k−2k−1∗num[i][k]\sum_{i=1}^n\sum_{k=1}^m C_{i+k-2}^{k-1} * num[i][k]∑i=1n​∑k=1m​Ci+k−2k−1​∗num[i][k]

对于num[i][k]num[i][k]num[i][k] 使用前缀和相减,num[i][k]=pre[n][k]−pre[i−1][k]num[i][k] = pre[n][k] - pre[i-1][k]num[i][k]=pre[n][k]−pre[i−1][k]

代码:

#include <bits/stdc++.h>#define int long long
using namespace std;
int const MAXN = 4200, mod = 1e9 + 7;int fac[MAXN], inv[MAXN];
int n, m, pre[MAXN][MAXN], num[MAXN][MAXN];int cnm(int n, int m) {if (n < m) return 0;if (m == 0) return 1;if (n == m) return 1;return (fac[n] * inv[n - m] % mod) * inv[m] % mod;
}int qmi(int a, int b) {int res = 1;while (b) {if (b & 1) res = res * a % mod;a = a * a % mod;b >>= 1;}return res;
}void init() {inv[1] = 1, fac[1] = 1, fac[0] = 1;for (int i = 2; i < MAXN; i++) fac[i] = fac[i - 1] * i % mod;inv[MAXN - 1] = qmi(fac[MAXN - 1], mod - 2);for (int i = MAXN - 2; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1) % mod;
}signed main() {cin >> n >> m;init();for (int k = 1; k <= m; k++) for (int j = 1; j <= n; j++) {pre[j][k] = pre[j - 1][k] + cnm(n - j + k - 1, k - 1);pre[j][k] %= mod;}for (int k = 1; k <= m; k++) for (int i = 1; i <= n; i++) {num[i][k] = pre[n][k] - pre[i - 1][k];num[i][k] %= mod;}int res = 0;for (int i = 1; i <= n; i++) for (int k = 1; k <= m; k++) {res = (res + cnm(i + k - 2, k - 1) * num[i][k]) % mod;}cout << (res + 1) % mod << endl;return 0;
}

C.Counting Cats!

题意:

题解:

代码:

#include <bits/stdc++.h>using namespace std;int const MAXN = 2e5 + 10;
int n, m, T;
map<string, int> mp;
int main() {ios_base::sync_with_stdio(false);cin.tie(NULL);cin >> n;for (int i = 1; i <= n; i++) {string s;cin >> s;mp[s]++;}int res = mp["cat"] + min(mp["ca"], mp["t"]) + min(mp["c"], mp["at"]);mp["t"] -= min(mp["ca"], mp["t"]);mp["c"] -= min(mp["c"], mp["at"]);res += min({mp["c"], mp["a"], mp["t"]});cout << res;return 0;
}

D.Dahno Dahno

题意:

题解:

代码:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <string>
#include <vector>
#define eps 1.0e-20
using namespace std;
#define mo 1000000000
#define inf 1000000000
#define int long longint cap[505][505];
int node[505], dis[505];
int Stoer_Wagner(int n) {int i, j, now, ans = 0x3fffffff;for (int i = 0; i < n; i++) node[i] = i;while (n > 1) {for (now = 0, i = 1; i < n; i++) dis[node[i]] = 0;for (i = 1; i < n; i++) {swap(node[now], node[i - 1]);for (now = j = i; j < n; j++) {dis[node[j]] += cap[node[i - 1]][node[j]];if (dis[node[now]] < dis[node[j]]) now = j;}}ans = min(ans, dis[node[now]]);for (j = 0; j < n; j++)cap[node[j]][node[now - 1]] = cap[node[now - 1]][node[j]] +=cap[node[j]][node[now]];node[now] = node[--n];}return ans;
}int n, m;
signed main() {cin >> n;int sum = 0;for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {scanf("%lld", &cap[i][j]);sum += cap[i][j];}}int cnt = Stoer_Wagner(n);cout << sum - 2 * cnt << endl;return 0;
}

E.Experiment Class

题意: 给定2条相交直线,给定2个点S和T,现在要求找到一条从S到T的路径,但是路径要经过2条直线各一次。求出最小路径权值。

题解:

初中几何题目

代码:

#include <bits/stdc++.h>using namespace std;
void duicheng(double a, double b, double c, double &x, double &y) {double x1 =((b * b - a * a) * x - 2 * a * b * y - 2 * a * c) / (a * a + b * b);double y1 =((a * a - b * b) * y - 2 * a * b * x - 2 * b * c) / (a * a + b * b);x = x1, y = y1;
}
int main() {double a, b, c, d, x0, y0, x1, y1;scanf("%lf%lf%lf%lf%lf%lf%lf%lf", &a, &b, &c, &d, &x0, &y0, &x1, &y1);if (y0 * x1 > y1 * x0) swap(x0, x1), swap(y0, y1);if (b * c > a * d) swap(a, c), swap(b, d);if (b * x0 < y0 * a) duicheng(-b, a, 0, x0, y0);if (c * y1 < x1 * d) duicheng(-d, c, 0, x1, y1);printf("%.3lf\n", sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)));return 0;
}

I.Identical Day

题意: 给定一个只含0和1构成的字符串,每次修改可以将某个1改为0.问最少修改几次能够使得该字符串的权值小于等于k?字符串的权值和定义为:xxxx见题意 1<=n<=1e5,0<=k<=1e101<=n<=1e5,0<=k<=1e101<=n<=1e5,0<=k<=1e10

题解: 首先看到这个题目第一眼,大家肯定知道平均分最好,比如你操作一次,那么尽可能把剩下的分成2段长度相等的。操作2次,那么尽可能分成3段长度相等的。那么每次到底分几段呢?

因为题目要求操作次数越小越好,那么就可以使用一个优先队列,每次从对头取出多份一段后使得权值变化最大的那个,然后维护变化完的状态,再次放入队列里面。具体见代码:

代码:

#include <bits/stdc++.h>#define int long longusing namespace std;const int maxm = 3e6 + 5;int cal(int x) { return x * (x + 1) / 2; }int get(int all, int cnt) {int num = all / cnt, rem = all % cnt;int c1 = cnt - rem, c2 = cnt - c1;int res = c1 * cal(num) + c2 * cal(num + 1);return res;
}struct Node {int all, cnt;bool operator<(const Node& a) const {int dif1 = get(all, cnt) - get(all - 1, cnt + 1);int dif2 = get(a.all, a.cnt) - get(a.all - 1, a.cnt + 1);return dif1 < dif2;}
};char s[maxm];
int n, k;void solve() {cin >> n >> k;cin >> (s + 1);int now = 0;priority_queue<Node> q;for (int i = 1, sizes = 0; i <= n; i++) {if (s[i] == '1') {sizes++;}if (sizes && (s[i] == '0' || i == n)) {now += get(sizes, 1);q.push({sizes, 1});sizes = 0;}}int res = 0;while (now > k) {Node x = q.top();q.pop();now -= get(x.all, x.cnt);x.all--;x.cnt++;now += get(x.all, x.cnt);if (x.all) {q.push(x);}res++;}cout << res << endl;
}signed main() {ios::sync_with_stdio(0);cin.tie(0);solve();return 0;
}

J.JXC&amp;Jesus

题意:

题解: 通过分析,可以发现其实影响的只有第一个素因子的幂次。然后因为L<=1e7,因此次数最多只有24位。那么直接筛素数的时候找到每个数字的最小素因子,然后暴力幂次即可。

代码:

#include <bits/stdc++.h>#define int long long
#define debug(x) cout << #x << " = " << x << endl;
using namespace std;inline int read() {int s = 0, w = 1;char ch = getchar();while (ch < '0' || ch > '9') {if (ch == '-') w = -1;ch = getchar();}while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();return s * w;
}int const MAXN = 2e7 + 10;
int n, m, T, cnt, L, st[MAXN], prime[MAXN], minp[MAXN];void get_prime(int n) {minp[1] = minp[0] = 1;for (int i = 2; i <= n; ++i) {if (!st[i])prime[cnt++] = i,minp[i] =i;  // 如果这个数字没有被记录,那么这个数字必然为素数,记录一下for (int j = 0; prime[j] <= n / i; ++j) {st[prime[j] * i] = true;  // 筛掉pj*i这个合数minp[prime[j] * i] = prime[j];if (i % prime[j] == 0)break;  // i%pj==0,说明pj是i的最小素因子,因此i*素数的最小素因子也是pj,在i递增的时候也会被筛掉,因此不需要在这里判断}}
}signed main() {// n = read(), m = read(), L = read();scanf("%lld%lld%lld", &n, &m, &L);get_prime(2e7 + 3);// for (int i = 1; i <= 10; ++i) cout << minp[i] << " ";int res = 0;for (int i = L + 1; i <= L + n; ++i) {int pMin = minp[i];int cnt = 0;int now = i;for (int j = 1; j <= 24; j++) {if (now % pMin == 0) {cnt++;now /= pMin;} elsebreak;}cnt /= m;for (int j = 1; j <= cnt; j++) now *= pMin;res += i - now;}printf("%lld\n", res);return 0;
}

K.Kazusa&rsquo;s Party

题意:

题解:

代码:

#include <bits/stdc++.h>using namespace std;int a[1000], b[1000], n;
signed main() {ios_base::sync_with_stdio(false);cin.tie(NULL);cin >> n;for (int i = 0; i < n; i++) cin >> a[i];for (int i = 0; i < n; i++) cin >> b[i];string ss = "";for (int i = 0; i < n; i++) ss += i + '0';int res = 0;while (1) {int temp = 0;for (int i = 0; i < n; i++) {if (__gcd(a[i], b[ss[i] - '0']) > 1) temp++;}res = max(res, temp);if (!next_permutation(ss.begin(), ss.end())) break;}cout << res << endl;return 0;
}

L.Little Witch Academia

题意:

题解: 先dfs求出所有每行的状态。然后对于h行,设f[i][S]f[i][S]f[i][S]:表示第i行状态为S时的方案数。则转移方程为:f[i][S]=∑S′&S==0f[i−1][S′]f[i][S] = \sum_{S' \& S ==0}f[i-1][S']f[i][S]=∑S′&S==0​f[i−1][S′]

这个式子用矩阵快速幂优化一下即可。

**代码: **

// 该代码没有调通,只过了60%样例,大佬懂得麻烦给我教我
#include <bits/stdc++.h>// #define int long long
using namespace std;typedef long long LL;int const N = 128;
int n, mod = 1e9 + 7;
struct mat {int m[N + 10][N + 10];
} unit;void init_unit() {for (int i = 1; i <= N; ++i) unit.m[i][i] = 1;
}void cout_mat(mat x) {for (int i = 1; i <= n; ++i) {for (int j = 1; j <= n; ++j) cout << x.m[i][j] << " ";cout << endl;}cout << endl;
}mat operator*(mat a, mat b) {mat c;memset(c.m, 0, sizeof c.m);  // 记得要初始化为0,否则值不为0for (int i = 1; i <= n; ++i)for (int j = 1; j <= n; ++j)for (int k = 1; k <= n; ++k)c.m[i][j] = (c.m[i][j] + (LL)a.m[i][k] * b.m[k][j] % mod) % mod;return c;
}mat qmi_mat(mat a, int k) {mat res = unit;// cout_mat(a);while (k) {if (k & 1) res = res * a;k >>= 1;a = a * a;}return res;
}mat f1, a;
int T, A, B, W, H;
int mp[N], cnt;void dfs(int cur, int s) {if (cur > W) return void();if (cur == W) return mp[++cnt] = s, void();if (cur + A <= W) dfs(cur + A, (cur + A == W) ? s : s | (1 << (cur + A)));if (cur + B <= W) dfs(cur + B, (cur + B == W) ? s : s | (1 << (cur + B)));
}signed main() {init_unit();cin >> T;for (int i = 1; i <= N; ++i) a.m[1][i] = 1;while (T--) {cnt = 0;cin >> A >> B >> W >> H;dfs(0, 0);n = cnt;// cout << "n := " << n << endl;memset(f1.m, 0, sizeof f1.m);for (int i = 1; i <= n; ++i)for (int j = 1; j <= n; ++j)if (i != j && !(mp[i] & mp[j])) f1.m[i][j] = 1;else f1.m[i][j] = 0;// cout << "f1:\n";// cout_mat(f1);H--;mat res;if (!H) res = unit;else res = qmi_mat(f1, H);// cout << "res:\n";// cout_mat(res);res = a * res;// cout_mat(res);int ans = 0;for (int i = 1; i <= n; ++i) ans = ((LL)ans + res.m[1][i] % mod) % mod;ans = (ans % mod + mod) % mod;cout << ans << endl;}return 0;
}

M.Minecraft

题意:

题解:

代码:

#include <bits/stdc++.h>using namespace std;int const N = 1e5 + 10;
int e[N], ne[N], h[N], idx, d[N];
int n, m, T, H;
char mp[100][100][100];
vector<int> ans;inline int read() {int s = 0, w = 1;char ch = getchar();while (ch < '0' || ch > '9') {if (ch == '-') w = -1;ch = getchar();}while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();return s * w;
}set<int> ss;
// 建立邻接表
void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; }// 拓扑排序
void top_sort() {priority_queue<int, vector<int>, less<int>> q;  // 这里是求字典序最小的拓扑序,如果求字典序最大的,那么改成// priority_queue<int, vector<int>, less<int>> q;for (int i = 1; i <= 26; ++i)if (!d[i] && ss.count(i)) q.push(i);  // 把入度为0的点加入队列// 当队列不为空时while (q.size()) {auto t = q.top();  // 取队头q.pop();           // 队头出队ans.push_back(t);  // 把这个数字放入答案序列for (int i = h[t]; i != -1; i = ne[i]) {  // 枚举所有队头元素相邻的元素int j = e[i];d[j]--;  // 队头元素出队相当于把与队头元素相连的元素的入度减一if (!d[j]) q.push(j);  // 把入度为0的元素放入队列}}if (ans.size() != ss.size()) {cout << -1 << endl;return;}for (int i = 0; i < ans.size(); ++i) {printf("%c", ans[i] - 1 + 'A');}cout << endl;
}int main() {T = read();while (T--) {ss.clear();memset(h, -1, sizeof h);memset(d, 0, sizeof d);ans.clear();idx = 0;n = read(), m = read(), H = read();for (int i = 0; i < H; ++i) {for (int j = 0; j < n; ++j) {cin >> mp[i][j];for (int k = 0; k < m; ++k) ss.insert(mp[i][j][k] - 'A' + 1);}}for (int i = 0; i < H - 1; ++i) {for (int j = 0; j < n; ++j) {for (int k = 0; k < m; ++k) {if (mp[i + 1][j][k] != mp[i][j][k]) {add(mp[i + 1][j][k] - 'A' + 1, mp[i][j][k] - 'A' + 1);// cout << mp[i + 1][j][k] - 'A' + 1 << "->" << mp[i][j][k] - 'A' + 1 << endl;d[mp[i][j][k] - 'A' + 1]++;}}}}top_sort();}return 0;
}

上海理工大学第二届“联想杯”全国程序设计邀请赛相关推荐

  1. 上海理工大学第二届“联想杯”全国程序设计邀请赛 - Little Witch Academia(矩阵快速幂)

    题目链接:点击查看 题目大意:给出两种型号的瓷砖,尺寸分别是 a∗1a*1a∗1 和 b∗1b*1b∗1,现在需要填满 w∗hw*hw∗h 的矩阵,需要满足以下两个情况: 瓷砖不能旋转 相邻的两行中, ...

  2. 上海理工大学第二届“联想杯”全国程序设计邀请赛 - Experiment Class(几何+三分套三分)

    题目链接:点击查看 题目大意:在二维平面的第一象限中给出两条射线代表河流,再给出起点和终点,问从起点出发,至少经过两条河各一次后到达终点的最短路 题目分析:如果只有一条河的话就是初中数学的经典问题了, ...

  3. 上海理工大学第二届“联想杯”全国程序设计邀请赛 - Dahno Dahno(SW)

    题目链接:点击查看 题目大意:给出一个有 nnn 个点的无向图,要求将其分成两个集合,使得总权值最大,每个集合需要非空 题目分析:SW模板题,套上即可 代码: // Problem: Dahno Da ...

  4. 上海理工大学第二届“联想杯”全国程序设计邀请赛 Identical Day 思维 + 暴力

    传送门 文章目录 题意: 思路: 题意: 给你一个010101序列,假设有一段长为lll连续的全111子串,定义这段字串不高兴值为l∗(l+1)2\frac{l*(l+1)}{2}2l∗(l+1)​, ...

  5. 2016第二届美亚杯全国电子数据取证大赛团队赛write up

    2016第二届美亚杯全国电子数据取证大赛 团队赛wp 本人TEL15543132658 同wechat,欢迎多多交流,wp有不足欢迎大家补充多多探讨! A部分write up 关于Hugo计算机的附加 ...

  6. 2016年 第二届美亚杯全国电子数据取证大赛个人赛write up

    2016年 第二届美亚杯个人赛write up 本人TEL15543132658 同wechat,欢迎多多交流,wp有不足欢迎大家补充多多探讨! 前景概要: 你会获得一个包含Hugo电脑硬盘的镜像文件 ...

  7. 第二届天府杯数学建模竞赛

    2022年第二届天府杯全国大学生数学建模竞赛正式官宣为省级赛事!四川省生产力促进中心挂牌在四川省自然资源科学研究院,是国家级生产力促进中心和国家级技术转移中心.想参加数模竞赛的快来报名啦~是由成都锦城 ...

  8. 2020 年 “联想杯”全国高校程序设计在线邀请赛暨第三届上海理工大学程序设计竞赛题解

    2020 年 "联想杯"全国高校程序设计在线邀请赛暨第三届上海理工大学程序设计竞赛题解 萌新又来写题解啦 原题链接 (不是按照题号顺序来的QWQ) L. Lottery Ticke ...

  9. 北京理工大学计算机学院赵曜,北理工学子参加第十届蓝桥杯全国软件和专业人才大赛取得佳绩...

    5月25日,第十届"蓝桥杯"全国软件专业人才设计与创业大赛在北京大学.首都经济贸易大学等多所高校同步举办.北京理工大学ACM俱乐部派出的21名参赛队员,经过长达四个小时的激烈角逐最 ...

最新文章

  1. python适合做后端开发吗-python适合后端开发么
  2. C#用了多线程界面还是卡死
  3. Windows Mobile设备操作演示准备工作小记
  4. win7 64-bit minifilter
  5. c++保留小数点后三位数_C++保留有效位与保留小数位
  6. My Brute(HDU-3315)
  7. SAP License:跨行如何转入SAP
  8. Android事件传递机制【Touch事件】
  9. 谭浩强C语言(第三版)习题6.11
  10. python设计模式之Borg模式
  11. 洛谷 P2525 Uim的情人节礼物·其之壱
  12. Japanese Student Championship 2021
  13. Found existing installation:xxxx
  14. 《软件工程之美》打卡第六周,春招我借这份PDF的复习思路
  15. 混沌与分形(一):谢尔宾斯基三角形与门格海绵
  16. 使用XMind 打开MindManager 格式文件(.mmap)
  17. 实时操作系统与分时操作系统(或称非实时操作系统)的区别
  18. 简单的JsonParser(Java)
  19. 【厚积薄发系列】C++项目总结9—ZeroMQ消息队列入门及分布式系统中应用(一)
  20. 基于mean-shift的简单目标跟踪

热门文章

  1. 属性编辑器 - 字体设置
  2. CSDN专题:谁将引领RIA的发展方向
  3. 基于Servlet+JSP+MySQL实现中医养生平台
  4. 数据本质价值的一些思考
  5. 三年三个大台阶 贝斯平(Bespin Global)将如何改变云管理行业?
  6. 【Games101 作业5】光线追踪 渲染小球
  7. CC2530学习温度传感器DS18B20
  8. 便携式Chrome浏览器
  9. 武汉科技大学c语言试题,武汉科技大学2011c语言考试A卷打印版.doc
  10. 唐诗宋词学习·136~140节