zoukankan      html  css  js  c++  java
  • P3396 哈希冲突 TJ

    题目链接

    思路

    暴力 (O(n^2).) 期望得分: (9.)
    考虑到此题有两种做法:
    (1.) (O(n^2)) 复杂度,每次询问的时候累加:

    ans = 0;
    for (int q = y;q <= n;q += x) {
    	ans += a[q];
    }
    printf ("%d
    ",ans);
    
    

    (2.) (O(n^2)) 的时间预处理,设 (f[i][j]) 表示模 (i) 等于 (j) 的数字总和。

    for (int q = 1;q <= n;++ q) {
    	for (int w = 1;w <= n;++ w) {
    		f[w][q % w] += a[q];
    	}
    }
    
    

    于是便有了一种新的思想,根号分治。
    顾名思义,根号分治就是前 (sqrt{n}) 的数据预处理,剩下的暴力求解。
    预处理复杂度为 (O(nsqrt{n})) ,那么剩下的询问 (p) 就超过了 (sqrt{n}) ,此时只有不到 (sqrt{n}) 个数对他有贡献,每一次暴力的复杂度 (O(sqrt{n}))
    剩下还有更改,需要 (O(sqrt{n})) 的时间处理 (f) 数组。
    总的时间复杂度是 (O((m + n)sqrt{n}).)

    代码

    暴力:(小学生都会写的)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int MAXN = 1e5 + 50010;
    int n, m ,a[MAXN] ,ans;
    int main () {
    	scanf ("%d%d",&n ,&m);
    	for (int q = 1;q <= n;++ q)
    		scanf ("%d",&a[q]);
    	int x ,y;
    	while (m --) {
    		ans = 0;
    		char ch = getchar ();
    		while (ch != 'A' && ch != 'C') ch = getchar ();
    		scanf ("%d%d",&x ,&y);
    		if (ch == 'A') {
    			for (int q = 1;q <= n;++ q) {
    				if (q % x == y) ans += a[q];
    			}
    			printf ("%d
    ",ans);
    		}
    		else a[x] = y;
    	}
    	return 0;
    }
    
    

    正解:

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    const int MAXN = 1e5 + 50010;
    int n ,m ,a[MAXN];
    int f[401][401];//f[i][j]表示模 i 余 j 的池的数的总和 
    int main () {
    	scanf ("%d%d",&n ,&m);
    	for (int q = 1;q <= n;++ q)
    		scanf ("%d",&a[q]);
    	int siz = sqrt (n);
    	for (int q = 1;q <= n;++ q) {
    		for (int w = 1;w <= siz;++ w) {
    			f[w][q % w] += a[q];
    		}
    	}
    //	for (int q = 1;q <= siz;++ q) {
    //		for (int w = 1;w <= siz;++ w) {
    //			printf ("mod %d = %d sum: %d
    ",q ,w ,f[q][w]);
    //		}
    //	}
    	int x ,y ,ans;
    	char ch;
    	while (m --) {
    		ch = getchar ();
    		while (ch != 'A' && ch != 'C') ch = getchar ();
    		scanf ("%d%d",&x ,&y);
    		if (ch == 'A') {
    			if (x <= siz) {
    				printf ("%d
    ",f[x][y]);
    			}
    			else {
    				ans = 0;
    				for (int q = y;q <= n;q += x) {
    					ans += a[q];
    				}
    				printf ("%d
    ",ans);
    			}
    		}
    		else {
    			int add_ = y - a[x];
    			for (int w = 1;w <= siz;++ w) {
    				f[w][x % w] += add_;
    			}
    			a[x] = y;
    		}
    	}
    	return 0;
    }
    
    
    cb
  • 相关阅读:
    用户与组
    初识linux
    权限管理
    认识vim 编辑器
    文件归档
    路由相关术语
    Access、Hybrid和Trunk
    #error作用
    交换芯片收发包的 DMA 实现原理
    linux网络学习
  • 原文地址:https://www.cnblogs.com/tuscjaf/p/13910542.html
Copyright © 2011-2022 走看看