2019广州二中CSP-S2前集训2019-11-13

文章目录

  • Problem A: 友好数对
    • 解题思路
  • Problem B: 绘画
    • 解题思路
  • Problem C: 线性规划问题
  • SOLUTION
    • A
    • B
    • C

样例下载 提取码2ihz

Problem A: 友好数对

2019广州二中CSP-S2前集训2019-11-13_第1张图片

解题思路

  • 80pts
    把a元素全部丢进hash表。枚举哪两位是1,对b进行操作然后在hash表中查询( O ( n l o g X ) O(nlogX) O(nlogX))
const int MAXN = 100005;
const int MO = 10000007;
int a[MAXN], b[MAXN];
int n, m;
ll ans;
struct Hash {
     
    int h[MO];
    int v[MAXN], nxt[MAXN], cnt;
    int geth(int x) {
        return x % MO;
    }
    void insert(int x) {
        v[++cnt] = x;
        nxt[cnt] = h[geth(x)];
        h[geth(x)] = cnt;
    }
    int count(int x) {
        int hs = geth(x);
        int ans = 0;
        for(rg int i = h[hs]; i; i = nxt[i]) {
            if(v[i] == x) ans++;
        }
        return ans;
    }
     
}hash;
int main() {
    //RS();
    n = read(), m = read();
    Rep(i, 1, n) a[i] = read();
    Rep(i, 1, m) b[i] = read();
    Rep(i, 1, m) hash.insert(b[i]);
    Rep(i, 0, 29)
        Rep(j, i + 1, 29) {
            int k = (1 << i) | (1 << j);
            Rep(l, 1, n)
                ans += hash.count(k ^ a[l]);
        }
    writeln(ans);
    return 0;
}
  • 100pts
    其实我们可以把两重循环拆成两个一重循环。题解里讲的很清楚
    但是!!! 写hash的时候注意了!!!
    1、模数不要随便取
    取什么1000007、19260817之类的就等着被卡把。
    2、要记录元素出现个数
    插入一个元素,不要直接插在链表头,而是应该遍历,寻找上次插入过的相同元素。这样可以避免太多相同元素 造成的退化。
    (这一题被卡得好惨。。。写hash还没有map快)
const int MAXN = 100005;
const int BASE = 29928197;
int n, m;
int a[MAXN], b[MAXN];
struct Hash_Table {
	struct Node {
		int v, nxt, num;
	}h[MAXN * 35];
	int head[BASE], cnt;
	int getpos(int x) {
		return x % BASE;
	}
	void insert(int x) {
		int pos = getpos(x);
		for(rg int i = head[pos]; i; i = h[i].nxt) {
			if(h[i].v == x) {
				h[i].num++;
				 return;
			}
		}
		h[++cnt].v = x;
		h[cnt].num = 1;
		h[cnt].nxt = head[pos];
		head[pos] = cnt;
	}
	int query(int x) {
		int pos = getpos(x);
		int ans = 0;
		for(rg int i = head[pos]; i; i = h[i].nxt)
			if(h[i].v == x) ans += h[i].num;
		return ans;
	}
}hash1, hash2;
ll equ, ans;
int main() {
	//RS();
	n = read(); m = read(); 
	for(rg int i = 1; i <= n; i++) a[i] = read(), hash2.insert(a[i]);
	for(rg int i = 1; i <= m; i++) b[i] = read();
	for(rg int i = 0; i <= 29; i++) 
		for(rg int j = 1; j <= n; j++)
			hash1.insert(a[j] ^ (1 << i));
	for(rg int i = 0; i <= 29; i++) 
		for(rg int j = 1; j <= m; j++) 
			ans += hash1.query(b[j] ^ (1 << i));
	for(rg int i = 1; i <= m; i++) equ += hash2.query(b[i]);
	writeln((ans - equ * 30) >> 1);
	return 0;
}

Problem B: 绘画

2019广州二中CSP-S2前集训2019-11-13_第2张图片
2019广州二中CSP-S2前集训2019-11-13_第3张图片

解题思路

真是一道毒瘤题。。。真是一道毒瘤题。
打完了这道题,你对二维前缀和就应该有深刻的理解了。。。

const int MAXN = 1005;
const int MAXK = 3e5 + 5;
const int MAXS = 30;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
int n, m, k, s;
char a[MAXN][MAXN];
int xl[MAXK], yl[MAXK], xr[MAXK], yr[MAXK];
int cl[MAXK];
ll cnt[MAXN][MAXN], ccnt[MAXN][MAXN][MAXS];
ll f[MAXN][MAXN];
ll ans = INF, id;
ll calc(int x1, int y1, int x2, int y2, int c) {
	ll ret = f[n][m] - (f[x2][y2] - f[x1 - 1][y2] - f[x2][y1 - 1] + f[x1 - 1][y1 - 1]);
	Rep(i, 0, s - 1) {
		ret += Abs(c - i) * (ccnt[x2][y2][i] - ccnt[x1 - 1][y2][i] - ccnt[x2][y1 - 1][i] + ccnt[x1 - 1][y1 - 1][i]);
	}
	return ret;
}
int main() {
	//RS();
	n = read(), m = read(), k = read(), s = read();
	Rep(i, 1, n) {
		scanf("%s", a[i] + 1);
		Rep(j, 1, m) a[i][j] -= 'a';
	}
	Rep(i, 1, k) {
		xl[i] = read(), yl[i] = read(), xr[i] = read(), yr[i] = read(), cl[i] = readc() - 'a';
		cnt[xl[i]][yl[i]]++, cnt[xr[i]+1][yr[i]+1]++, cnt[xl[i]][yr[i]+1]--, cnt[xr[i]+1][yl[i]]--; 
		ccnt[xl[i]][yl[i]][cl[i]]++, ccnt[xr[i]+1][yr[i]+1][cl[i]]++, ccnt[xl[i]][yr[i]+1][cl[i]]--, ccnt[xr[i]+1][yl[i]][cl[i]]--;		
	}
	Rep(i, 1, n)
		Rep(j, 1, m) {
			cnt[i][j] += cnt[i - 1][j] + cnt[i][j - 1] - cnt[i - 1][j - 1];
			Rep(l, 0, s - 1)
				ccnt[i][j][l] += ccnt[i - 1][j][l] + ccnt[i][j - 1][l] - ccnt[i - 1][j - 1][l];	
		}
	Rep(i, 1, n)
		Rep(j, 1, m)
			ccnt[i][j][a[i][j]] += k - cnt[i][j];
	Rep(i, 1, n)
		Rep(j, 1, m) {
			f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1];
			Rep(l, 0, s - 1) 
				f[i][j] += Abs(l - a[i][j]) * ccnt[i][j][l];
		}
	Rep(i, 1, n)
		Rep(j, 1, m)
			Rep(l, 0, s - 1)
				ccnt[i][j][l] += ccnt[i - 1][j][l] + ccnt[i][j - 1][l] - ccnt[i - 1][j - 1][l];
	Rep(i, 1, k) {
		ll ret = calc(xl[i], yl[i], xr[i], yr[i], cl[i]);
		if(ret < ans) {
			ans = ret;
			id = i;
		}
	}
	writesp(ans), writeln(id);
	return 0;
}

Problem C: 线性规划问题

2019广州二中CSP-S2前集训2019-11-13_第4张图片
2019广州二中CSP-S2前集训2019-11-13_第5张图片

SOLUTION

A

2019广州二中CSP-S2前集训2019-11-13_第6张图片

B

2019广州二中CSP-S2前集训2019-11-13_第7张图片
2019广州二中CSP-S2前集训2019-11-13_第8张图片

C

2019广州二中CSP-S2前集训2019-11-13_第9张图片
2019广州二中CSP-S2前集训2019-11-13_第10张图片

你可能感兴趣的:(集训,题解)