首页 > 其他分享 >mutiset 哈希 思维

mutiset 哈希 思维

时间:2023-06-07 12:23:14浏览次数:39  
标签:思维 cnt nxt min int max mutiset 哈希 div

D. GCD of an Array

https://codeforces.com/problemset/problem/1493/D
题意:给定一个序列,有q次询问,每次将其中一个数×上ki,问每次操作后全体gcd为多少。
n,q<=2e5.
题解:这题思路很一眼,无非是维护每一个数的素因数以及其指数,存每个数中素因数出现的次数,每次操作判断改变后的素因数集合中最小元素。问题主要是实现,具体而言我们可以用map[i]维护每一个数的素因数出现次数,用mutiset[p]维护素数p在各个a[i]中出现的次数,若没出现则不放入,每次求最小元素即可,单次询问复杂度为log*log。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int const maxn = 2e5 + 5, max_val = 2e5 + 5;
ll mod = 1e9 + 7, ans = 1;
int nxt[max_val], n;
multiset <int> cnt[max_val];
map <int, int> cnt_divisor[maxn];

void add(int i, int x) {
    while (x != 1) {
        int div = nxt[x], add = 0;
        while (nxt[x] == div) add++, x = x / nxt[x];

        int lst = cnt_divisor[i][div];
        cnt_divisor[i][div] += add;
        int lst_min = 0;
        if ((int)cnt[div].size() == n) {
            lst_min = (*cnt[div].begin());
        }
        if (lst != 0) {
            cnt[div].erase(cnt[div].find(lst));
        }
        cnt[div].insert(lst + add);
        if ((int)cnt[div].size() == n) {
            for (int j = lst_min + 1; j <= (*cnt[div].begin()); ++j) {
                ans = ans * (ll)div % mod;
            }
        }
    }
}

main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int q, l, x;
    cin >> n >> q;

    for (int i = 2; i < maxn; ++i) {
        if (nxt[i] == 0) {
            nxt[i] = i;
            if (i > 10000) continue;
            for (int j = i * i; j < maxn; j += i) {
                if (nxt[j] == 0) nxt[j] = i;
            }
        }
    }

    for (int i = 1; i <= n; ++i) {
        cin >> x;
        add(i, x);
    }

    for (int i = 1; i <= q; ++i) {
        cin >> l >> x;
        add(l, x);
        cout << ans << '\n';
    }

    return 0;
}

B. BinCoin 哈希

https://codeforces.com/problemset/problem/1773/B
题意:给定n个点,组成一棵二叉树,给出k个排列,每个表示对这个二叉树的一种遍历,具体而言,从根节点开始,若该点无子节点,则记录后传给父节点,否则随机选择一个儿子下发,再次传上时记录。还原该树。
n<=1000,50<=k<=100
题解:这题的性质也比较好观察,即对一颗子树,其根节点左右两侧元素集合总是那两个集合,那么我们可以每次找到根后拆分问题求解,但直接做复杂度为nnnk,问题在于对集合的处理。我们对点做哈希,hash[i]=2^i%mod.再对于每个排列计算前缀和,这样我们的询问不需要nk,只需要k即可,最后总复杂度为nn*k.

E. Node Pairs

https://codeforces.com/problemset/problem/1763/E
题意:我们称有序对为u!=v&u->v可达但v->u不可达。我们定义p可达图为图中有p对点两两可互相到达,则现在给你一个数k,问需要构建一张图k可达,至少需要多少个点,同时,再满足最少点数情况下,最多有多少有序对。
k<=2e5
题解:观察发现,组成可达对的点是又一组组完全图组成的,换言之,我们即为求将k分解为若干个n(n-1)/2形式的数之和,问最小点数。我们可以dp求解,dp(i)表示k=i时,表示k所需的最小点数,f(i)=min(f(i),f(i-a(j))+j),a(j)表示为j个点形成的可达对数量,由于 a[j]=j(j-1)/2,故复杂度为n*sqrt(n).
而对于如何最大化有序对,即可转化为现有w个点,每个点有一个权值,u->v使得答案增加二者之积,且图为有向无环图。我们可以贪心地得到答案,我们每次取集合中最大的数,将其与所有剩下的数连边,这样结果必定最大且不存在环,证明很显然,留给读者。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10,mod=1e9+7;
int a[N],b[N],f[N],pre[N],s[N];
signed main(){
	int n;cin>>n;
	for(int i=2;i<=10000;i++){
		a[i]=(i-1)*i/2;
	}
	for(int i=1;i<=n;i++) f[i]=1e18;
	for(int i=1;i<=n;i++){
		for(int j=2;;j++){
			if(a[j]>i) break;
			if(f[i]>f[i-a[j]]+j) pre[i]=j;
			f[i]=min(f[i],f[i-a[j]]+j);
		}
	}
	int x=n,t=0;
	while(x){
		int w=pre[x];
		b[++t]=w;
		x-=a[w];
	}
	cout<<f[n]<<" ";
	sort(b+1,b+t+1);
	for(int i=1;i<=t;i++){
		s[i]=s[i-1]+b[i];
	}
	int ans=0;
	for(int i=t;i>=1;i--){
		ans+=b[i]*(s[i-1]);
	}
	cout<<ans;
}

E. A-Z Graph

https://codeforces.com/contest/1494/problem/E
题意:给定一个包含 n 个顶点的有向图。每个有向边(或弧)都标有一个字符。初始时,图为空。
你需要处理 m 个查询。每个查询有三种类型之一:1,u,v

标签:思维,cnt,nxt,min,int,max,mutiset,哈希,div
From: https://www.cnblogs.com/wjhqwq/p/17462986.html

相关文章

  • [科技] 异或哈希
    一个小问题Statement来源:https://www.luogu.com.cn/problem/T297472?contestId=91205给定字符串\(S\),求最长的连续子序列满足其中每个字符都出现了偶数次,求最长长度。\(T\)组询问,\(\displaystyle\sum_{}|S|\leq5\times10^6\)。注:本题暂时只需要通过\(\text{Subtask4}......
  • 逆向思维获取他人信任
    以往的做法以往的做法往往是尽量收集受害人信息,从而简历与受害人之间的信任,随着人们对个人信息的重视以及官方对诈骗分子的宣传,大部分人都拥有极高的警惕性,而且收集一个人尽可能多的信息从而应对各种***钻古怪的问题并不容易,这样的成本显然是极高的。反向建立自己与受害人之间的......
  • 管理思维
    管理思维切入点是什么中长期规划是什么收益和价值是什么如何通过指标度量拆解后的能力阶段建设和交付思路是什么为了做成事情人员的配比逻辑是什么你在人才识别和培养上的逻辑和现状是什么业务思考需要结合内部和外部(业界)来看,我们和精品的区别、差异、优势和劣势是什么明确的定位到......
  • 最小哈希 minhash
    最小哈希维基百科,自由的百科全书 在计算机科学领域,最小哈希(或最小哈希式独立排列局部性敏感哈希)方法是一种快速判断两个集合是否相似的技术。这种方法是由AndreiBroder (1997),[1]发明的,最初在AltaVista搜索引擎中用于在搜索结果中检测并消除重复Web页面。[2]它同样也应用于大规模......
  • leetcode2352哈希表的键可以是一个容器等类型
    map<vector<int>,int>cnt;//用于存储每个行向量出现的次数for(autorow:grid){//直接遍历行向量cnt[row]++;}for(inti=0;i<n;++i){vector<int>arr;for(intj=0;j<n;++j){//存储列向量arr.emplace_back(grid[j][i]);}if(cnt.find(arr)!=cnt.......
  • 数据治理专业认证CDMP学习笔记(思维导图与知识点)- 第10章参考数据和主数据篇
    大家好,我是独孤风,一位曾经的港口煤炭工人,目前在某国企任大数据负责人,公众号大数据流动主理人。在最近的两年的时间里,因为公司的需求,还有大数据的发展趋势所在,我开始学习数据治理的相关知识。数据治理需要进行系统的学习才能真正掌握,也需要进行专业的考试认证才能证明自己在数据治理......
  • 谈谈一致性哈希算法
    一致性哈希算法是1997年由麻省理工的几位学者提出的用于解决分布式缓存中的热点问题。大家有没有发现,我们之前介绍的例如快排之类的算法是更早的六七十年代,此时分布式还没有发展起来,大家往往还在提高单机性能。但是九十年代开始,逐渐需要用分布式集群来解决大型问题,相应的算法研究......
  • 从“PRD怎么写”说到产品思维
    PRD怎么写?这个问题可以算是困扰产品新人排名前三的问题之一了。但我显然不会具体说应该怎么写,不会说模板、形式、原则这些落地的东西,而想和大家聊聊,怎么把产品思维反作用于回答这个问题,反作用于产品工作本身。第一,问专家不如问用户。如果我们把PRD也看做一个产品,那么用户就是开发、......
  • Gym - 101170A[DP+思维]
    题目链接:https://vjudge.net/problem/Gym-101170A 解题思路:首先要确定的是,改变次数最多不会超过2*n次,因为n最多40,所以我们只要改变每个数的前两个最高位,肯定可以让n个数有序。然后我们就可以想办法搞个DP[i][j]表示将前i个数变成有序花了j次的最小值。为什么是最小值呢,维护最小......
  • CodeForcese 1256F [思维]
    题目链接:https://codeforces.com/problemset/problem/1256/F 解题思路:任意的翻转都可以认为是翻转若干个长度为2的,交换两个数主要奇数次翻转。两个串可以翻转成一样,那么一定可以再花费一样的翻转次数变成有序的字符串,连续两个相等的字符翻转任意数次是一样的,所以只要有两个字符......