E - AtCoder Express 2
思路:转化为二维前缀和,查询时查(y,y)和(x,x)之间的范围
#include
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(fast)
#include
#include
#include
1640 天气晴朗的魔法
思路:先kruskal算法求最小生成树中的最大边的最小值,再求最大生成树,使用快读,cin时间超限
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ms(x,y) memset(x,y,sizeof x);
#define YES cout<<"YES"<<'\n';
#define NO cout<<"NO"<<'\n';
#define endl cout<<'\n';
typedef long long ll;
const ll maxn=2e5+10,inf = 1e18 ;
const ll mod = 1e9 + 7;
using namespace std;
using namespace std;
typedef long long ll;
int f[maxn];
ll Max_Edge;
inline int read()
{
int f = 1;
int x = 0;
char c = getchar();
while (c < '0' || c>'9') {
if (c == '-') {
f = -f;
}
c = getchar();
}
while (c >= '0' && c <= '9') {
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return x * f;
}
struct edge {
int u, v;
ll w;
}a[maxn];
bool cmp1(edge A, edge B) {
return A.w < B.w;
}
bool cmp2(edge A, edge B) {
return A.w > B.w;
}
int find(int x) {
if (f[x] == -1) return x;
return f[x] = find(f[x]);
}
int n, m;
int kruskal1() {
// 返回最小生成树的最后一条边的下标 ans
// Edge[ans].v 为最小生成树中的最大边
memset(f, -1, sizeof(f));
int num = 0, ans = 1;
for (int i = 1; i <= m; i++) {
int s= find(a[i].u);
int e = find(a[i].v);
if (s != e) {
num++;
ans = i;
f[min(s,e)] = max(s,e);
}
if (num >= n - 1) {
break;
}
}
if (num >= n - 1) {
return ans;
}
else {
return -1;
}
}
ll kruskal2() {
// 在所有小于等于 Max_Edge 的边中求得最大生成树
memset(f, -1, sizeof(f));
ll ans = 0, num = 0;
for (int i = 1; i <= m; i++) {
if (a[i].w > Max_Edge)
continue;
int s = find(a[i].u);
int e = find(a[i].v);
if (s != e) {
num++;
ans += a[i].w;
f[min(s, e)] = max(s, e);
}
if (num >= n - 1)
break;
}
if (num >= n - 1)
return ans;
return -1;
}
int main() {
cin >> n >> m;
int u, v, w;
for (int i = 1; i <= m; i++) {
u = read();
v = read();
w = read();
a[i].u = u, a[i].v = v;
a[i].w = w;
}
sort(a + 1, a + m + 1, cmp1); // 升序,最小生成树
int index = kruskal1();
Max_Edge = a[index].w;
sort(a + 1, a + m + 1, cmp2); // 降序,最大生成树
cout << kruskal2();
return 0;
}
3D模型
思路:首先计算一个柱面的表面积,之后减去重合的面积
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ms(x,y) memset(x,y,sizeof x);
#define YES cout<<"YES"<<'\n';
#define NO cout<<"NO"<<'\n';
#define endl cout<<'\n';
typedef long long ll;
const ll maxn=1e3+10,inf = 1e18 ;
const ll mod = 1e9 + 7;
using namespace std;
int a[maxn][maxn], ans;
void solve() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%1d", &a[i][j]);
if (a[i][j] == 0) continue;
ans += a[i][j] * 4 + 2;
ans -= min(a[i - 1][j], a[i][j]) * 2;
ans -= min(a[i][j - 1], a[i][j]) * 2;
}
}
cout << ans << '\n';
}
int main() {
solve();
return 0;
}
J - Blue and Red Balls
题意:k个蓝球,n-k个红球,把k个蓝球分成m堆,放进红球中,有多少种方案
思路:m堆放进红球,(插空法)有C(n-k+1,m)方案数,分成m堆(,隔板法)有C(k-1,m-1)
#include
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(fast)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ms(x,y) memset(x,y,sizeof x);
#define YES cout<<"YES"<<'\n';
#define NO cout<<"NO"<<'\n';
#define endl cout<<'\n';
typedef long long ll;
const ll maxn=2e5+10,inf = 1e18 ;
const ll mod = 1e9 + 7;
using namespace std;
int a[maxn];
ll inv(ll a,ll m) { //线性地推,不进行储存
if (a == 1)return 1;
return inv(m % a, m) * (m - m / a) % m;
}
ll C(int a, int b) { //组合计算的快速方法1,b>=a
ll t1 = 1, t2 = 1;
for (int i = b; i >= (b - a + 1); i--)t1 = t1 * i % mod;
for (int i = a; i >= 1; i--)t2 = t2 * i % mod;
return t1 * inv(t2, mod) % mod;
}
void solve(){
int n, k;
cin >> n >> k;
for (int i = 1; i <= k; i++) { //枚举堆数
cout << (C(i, n - k +1)%mod * C(i - 1, k - 1) % mod)%mod << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
int t=1;
//cin >> t;
while (t--) {
solve();
}
}