【校内互测】Rivendell’s pearls(字符串哈希+容斥)

2023-10-04 22:50

本文主要是介绍【校内互测】Rivendell’s pearls(字符串哈希+容斥),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Rivendell’s pearls(pearls.cpp)
【问题描述】
    Rivendell 是一个心灵手巧的男孩子,他在闲暇的时候喜欢做一些小饰品。有一天 Rivendell用漂亮的珍珠做成了 n串手链,并且每串手链都由 4个珍珠构成,并且每粒珍珠都有一种颜色,颜色用小写字母和数字表示。现在他突然想知道这n 串手链中有多少对有且仅有k 粒珍珠是不同颜色的。
【输入格式】
   第一行两个整数 n和 k。接下来 n个长度为 4的字符串。
【输出格式】
     一个整数表示答案。
【样例输入】
    4 2
    0000
    a010
    0202
    a0e2
【样例输出】
    3
【数据规模及约定】
   对于15%的数据,n<=2000
   对于 60%的数据,k<=2。其中50%的数据,k=1

   对于 100%的数据,n<=50000,k<=4

————————————————————————————————

【题解】【字符串哈希+容斥】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int hash[50010],sum[50010][4];
ll ans[5];
int n,k;
inline int change(char x)
{if(x>='0'&&x<='9') return x-'0';return x-'a'+10;
}
inline ll cal(int n)
{ll sm=0;int i,x=1;sort(hash+1,hash+n+1);for(i=2;i<=n;++i)if(hash[i]==hash[i-1]) x++;else sm+=(ll)(x-1)*x/2,x=1;sm+=(ll)(x-1)*x/2;return sm;
}
int main()
{freopen("pearls.in","r",stdin);freopen("pearls.out","w",stdout);int i,j,l;scanf("%d%d",&n,&k);for(i=1;i<=n;++i){char s[5];scanf("%s",s);for(j=0;j<4;++j) sum[i][j]=change(s[j]);}for(i=1;i<=n;++i)for(j=0;j<4;++j)hash[i]=hash[i]*36+sum[i][j];ans[0]=cal(n);for(l=0;l<4;++l){memset(hash,0,sizeof(hash));for(i=1;i<=n;++i){for(j=0;j<l;++j) hash[i]=hash[i]*36+sum[i][j];for(j=l+1;j<4;++j) hash[i]=hash[i]*36+sum[i][j];}ans[1]+=cal(n);}ans[1]-=ans[0]*4;if(k==1) {printf("%I64d\n",ans[1]); return 0;}for(l=0;l<4;++l)for(i=l+1;i<4;++i){for(j=1;j<=n;++j) hash[j]=sum[j][l]*36+sum[j][i];ans[2]+=cal(n);}ans[2]-=(ans[0]*4+ans[1]*3);if(k==2) {printf("%I64d\n",ans[2]); return 0;}for(l=0;l<4;++l){for(i=1;i<=n;++i) hash[i]=sum[i][l];ans[3]+=cal(n);}ans[3]-=(ans[2]*2+ans[1]*3+ans[0]*4);if(k==3) {printf("%I64d\n",ans[3]); return 0;}ans[4]=(ll)(n-1)*n/2-ans[3]-ans[2]-ans[1]-ans[0];printf("%I64d\n",ans[4]);return 0;
}


这篇关于【校内互测】Rivendell’s pearls(字符串哈希+容斥)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/2895

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

hdu4407容斥原理

题意: 有一个元素为 1~n 的数列{An},有2种操作(1000次): 1、求某段区间 [a,b] 中与 p 互质的数的和。 2、将数列中某个位置元素的值改变。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.Inpu

hdu4059容斥原理

求1-n中与n互质的数的4次方之和 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWrit

哈希表的底层实现(1)---C++版

目录 哈希表的基本原理 哈希表的优点 哈希表的缺点 应用场景 闭散列法 开散列法 开放定值法Open Addressing——线性探测的模拟实现 超大重点部分评析 链地址法Separate Chaining——哈希桶的模拟实现 哈希表(Hash Table)是一种数据结构,它通过将键(Key)映射到值(Value)的方式来实现快速的数据存储与查找。哈希表的核心概念是哈希

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

哈希表的封装和位图

文章目录 2 封装2.1 基础框架2.2 迭代器(1)2.3 迭代器(2) 3. 位图3.1 问题引入3.2 左移和右移?3.3 位图的实现3.4 位图的题目3.5 位图的应用 2 封装 2.1 基础框架 文章 有了前面map和set封装的经验,容易写出下面的代码 // UnorderedSet.h#pragma once#include "HashTable.h"

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

C和指针:字符串

字符串、字符和字节 字符串基础 字符串就是一串零个或多个字符,并且以一个位模式为全0的NUL字节结尾。 字符串长度就是字符串中字符数。 size_t strlen( char const *string ); string为指针常量(const修饰string),指向的string是常量不能修改。size_t是无符号数,定义在stddef.h。 #include <stddef.h>