T1
思路
只要会sort就能a
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100000 + 100;
typedef long long ll;
ll read() {
ll x = 0, f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
int a[N],b[N];
bool cmp(int x,int y) {
return x > y;
}
int main() {
freopen("stone.in","r",stdin);
freopen("stone.out","w",stdout);
int T = read();
while(T--) {
int n = read(), m = read();
for(int i = 1;i <= n;++i) a[i] = read();
for(int i = 1;i <= m;++i) b[i] = read();
ll ans = 0;
sort(a+1,a+n+1,cmp);
sort(b+1,b+m+1);
int k = min(n,m);
for(int i = 1;i <= k;++i) {
int z = a[i] - b[i];
if(z <= 0) break;
ans = ans + z;
}
printf("%lld
",ans);
}
return 0;
}
T2
思路
据说标程是(O(n^3))dp,然而我写了O(nlogk)的容斥。因为二进制的每一位是互不影响的,所以可以先考虑k = 1时的做法。考虑先不管行,只考虑每一列满足条件会有多少种情况。假设有m行,那么对于每一列都有(2^n)种情况,其中只有全都是0的一种情况是不满足条件的。所以每一列满足条件的情况数就是(2^n-1)。因为有m列,所以就是((2^n-1)^m)种情况。然后在考虑减去有某一行,某两行...某n行不满足条件的情况。自然就考虑到了容斥。
用f[i]表示只考虑i行m列的时候每一列都满足条件的情况数。怎么求上面已经说了。容斥式子就是$$sumlimits_{i = 0}^n{f[i] * C_n^i * (-1)^i}$$
代码
#include<cstdio>
#include<iostream>
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
const int N = 100;
ll read() {
ll x = 0, f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
ll ksm(ll x,ll y) {
if(x == 0) return 0;
ll ans = 1;
for(;y;y >>= 1,x = x * x % mod) {
if(y & 1) ans = ans * x % mod;
}
return ans;
}
ll C[N][N];
void pre() {
C[0][0] = 1;
for(int i = 1;i <= 60;++i) {
C[i][0] = 1;
for(int j = 1;j <= i;++j) {
C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;
}
}
}
ll n, m ,k;
ll f(ll x) {
return ksm((ksm(2,x) - 1),m);
}
int main() {
freopen("code.in","r",stdin);
freopen("code.out","w",stdout);
int T = read();
pre();
while(T--) {
n = read(),m = read(), k = read();
if(n > m) swap(n,m);
ll ans = 0;
for(int i = 0;i <= n;++i) {
ll b = 1;
if(i & 1) b = -1;
ans += (C[n][i] * f(n - i) * b % mod+ mod )% mod;
ans >= mod ? ans -= mod:0;
}
printf("%lld
",((ksm(ans,k)) % mod + mod ) % mod);
}
return 0;
}
T3
心路历程
为什么这个题没有思路而是心路历程?因为不会啊啊
真的不知道该怎么吐槽这个题了。先是发一个假的大样例,导致改暴力改了1h,然后说重新发样例,结果把第四个数据给发下来了。然后我并不知道这是数据。然后看见我的暴力re了。还以为要离散化。然后还是re,然后发现样例不是在暴力数据范围内的。然后删离散化,再给回去。然后就交卷了。fu*k。最后标程180行。90分的老哥写了230行。。。。。cnm
暴力代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
const int N = 100000 + 100;
typedef unsigned int lint;
lint read() {
lint x = 0, f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
map<int,int>ma;
int a[700][700];
struct node {
int x,y,w;
}e[700 * 700];
int ls[1000];
lint n ,m , q;
int main() {
freopen("triangle.in","r",stdin);
freopen("triangle.out","w",stdout);
int T = read();
while(T--) {
n = read(), m = read(),q = read();
// cout<<n<<endl;
memset(a,0,sizeof(a));
if(m < 3) { puts("0");continue;}
int js = 0;
while(q--) {
int u = read(),v = read(),w = read();
e[++js].x = u,e[js].y = v;e[js].w= w;
ls[++ls[0]] = u;ls[++ls[0]] = v;
}
sort(ls+1,ls + ls[0] + 1);
int now = 0;
ma[ls[1]] = ++now;
for(int i = 2;i <= ls[0];++i) {
if(ls[i] != ls[i-1]) ma[ls[i]] = ++ now;
}
for(int i =1 ;i<= js;++i) {
int x = ma[e[i].x],y = ma[e[i].y];
a[x][y] = a[y][x] = e[i].w;
}
lint ans = 0;
for(int i = 1;i <= n;++i) {
for(int j = 1;j < i;++j) {
for(int k = 1;k < j;++k) {
if(((a[i][j] == a[i][k] || a[i][j] == a[j][k]) && a[i][j] != 0) || (a[j][k] == a[i][k] && a[j][k] != 0)) continue;
lint x = 3,y = 0;
if(a[i][j]) x--,y++;if(a[i][k]) x--,y++;if(a[j][k]) x--,y++;
lint t = 1;
lint mm = m - y;
for(int z = 0;z < x;++z) {
t *= (mm - z);
}
ans += t;
}
}
}
cout<<ans<<endl;
}
return 0;
}
总结
期望得分:100 + 100 + 30 = 230
实际得分:100 + 100 + 30 = 230
前两个题写完的比较早,时间基本上都花在了t3上。然而t3还是只有30分。
一言
因为有了因为,所以有了所以。既然已成既然,何必再说何必。 ——因为