POJ 3349&&3274&&2151&&1840&&2002&&2503
(今天兴致大发学了Markdown,第一篇博客)
这次的主要都是hash的题目(当然这就意味这可以用map)
hash的方式也有很多:
普通hash
hash挂链
双hash以及自然溢出等
当然我还是喜欢挂链的(主要是精准)
下面开始看题目
3349
题意很简单,给出一片雪花的信息(六个角)
如果两片雪花相同则它们从某一点开始顺时针或逆时针数字相同
这...... 直接hash跑一边即可
主意挂链,要不然很容易WA
CODE
#include<cstdio>
#include<cstring>
using namespace std;
const int mod=2333333,N=100005;
struct edge
{
int to,next;
}link[N];
int head[mod],sum,n,a[N][10],k;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline void add(int x,int y)
{
link[++k].to=y; link[k].next=head[x]; head[x]=k;
}
inline bool check(int x,int y)
{
for (register int i=1;i<=6;++i)
{
int p1=i,p2=1;
while (p2<=6)
{
if (a[x][p1]!=a[y][p2]) break;
if (++p1>6) p1-=6; ++p2;
}
if (p2>6) return 1;
}
for (register int i=1;i<=6;++i)
{
int p1=i,p2=1;
while (p2<=6)
{
if (a[x][p1]!=a[y][p2]) break;
if (--p1<1) p1+=6; ++p2;
}
if (p2>6) return 1;
}
return 0;
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i,j;
memset(link,-1,sizeof(link));
memset(head,-1,sizeof(head));
read(n);
for (i=1;i<=n;++i,sum=0)
{
for (j=1;j<=6;++j)
read(a[i][j]),sum+=a[i][j];
int k=sum%mod;
for (j=head[k];j!=-1;j=link[j].next)
if (check(i,link[j].to)) { puts("Twin snowflakes found."); return 0; }
add(k,i);
}
puts("No two snowflakes are alike.");
return 0;
}
3274
题目大意是有n头奶牛,每个奶牛有k个特征值(用2进制下的每一位上的数来表示)
让你求一段最长的区间,使得其中奶牛的所有特征值的和分别相等
这里用sum[i][j]来表示前i头奶牛中第j个特征值的和
所以我们发现题目要求是找最长的区间l,r满足
sum[r][1]-sum[l-1][1]=sum[r][2]-sum[l-1][2]=sum[r][3]-sum[l-1][3]=...=sum[r][k]-sum[l-1][k]
对上面的式子分析后移项得:
- sum[r][1]-sum[r][1]=sum[l-1][1]-sum[l-1][1]
- sum[r][2]-sum[r][1]=sum[l-1][2]-sum[l-1][1]
- sum[r][3]-sum[r][1]=sum[l-1][3]-sum[l-1][1]
- ...
- sum[r][k]-sum[r][1]=sum[l-1][k]-sum[l-1][1]
所以我们将sum[i]j的每一项都减去sum[i][1]
然后对于每一个i,找一下是否有和它相同的sum[i]序列
hash即可
CODE
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100005,K=35,seed=2333,mod=2333333;
struct edge
{
int to,next;
}link[N];
int n,k,head[mod],sum[N][K],sign[N][K],x,ans,tot;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline int hash(int x)
{
int res=1,t;
for (register int i=1;i<=k;++i)
{
if ((t=sign[x][i])<0) t=-sign[x][i]*2;
res=((long long)t*seed+res)%mod;
}
return res;
}
inline int max(int a,int b)
{
return a>b?a:b;
}
inline void add(int x,int y)
{
link[++tot].to=y; link[tot].next=head[x]; head[x]=tot;
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i,j,p;
read(n); read(k);
memset(link,-1,sizeof(link));
memset(head,-1,sizeof(head));
for (i=1;i<=n;++i)
{
read(x);
for (j=1;j<=k;++j,x>>=1)
if (x&1) sum[i][j]=sum[i-1][j]+1; else sum[i][j]=sum[i-1][j];
}
for (i=1;i<=n;++i)
for (j=1;j<=k;++j)
sign[i][j]=sum[i][j]-sum[i][1];
for (i=0;i<=n;++i)
{
int now=hash(i);
for (j=head[now];j!=-1;j=link[j].next)
{
bool flag=1;
for (p=1;p<=k;++p)
if (sign[link[j].to][p]^sign[i][p]) { flag=0; break; }
if (flag) ans=max(ans,i-link[j].to);
}
add(now,i);
}
printf("%d",ans);
return 0;
}
2151
这道题来错了地方
它其实是一道概率DP的题目
因此这里不进行讨论
1840
题意大概是让你求五元三次方程a1x13+a2x23+a3x33+a4x43+a5x53=0在[-50,50]范围内整数解集的个数
给出ai(1<=i<=5)
这道题最先想到的肯定就是枚举了,然而T到死(100^5)
所以我们还是移项,将原式变为:
-a1x13-a2x23=a3x33+a4x43+a5x53
然后对于-a1x13-a2x23进行hash后再枚举x3,x4,x5
复杂度陡然降低至O(1003+1002)
CODE
#include<cstdio>
#include<cstring>
using namespace std;
const int mod=2333333;
struct edge
{
int to,next;
}link[10005];
int head[mod],a[10],ans,tot;
inline int hash(int x)
{
if (x<0) x=-2*x;
return x%mod;
}
inline void add(int x,int y)
{
link[++tot].to=y; link[tot].next=head[x]; head[x]=tot;
}
int main()
{
memset(link,-1,sizeof(link));
memset(head,-1,sizeof(head));
register int i,j,k,p;
for (i=1;i<=5;++i)
scanf("%d",&a[i]);
for (i=-50;i<=50;++i)
for (j=-50;j<=50;++j)
{
if (!i||!j) continue;
int t=a[1]*i*i*i+a[2]*j*j*j;
add(hash(-t),t);
}
for (i=-50;i<=50;++i)
for (j=-50;j<=50;++j)
for (k=-50;k<=50;++k)
{
if (!i||!j||!k) continue;
int t=a[3]*i*i*i+a[4]*j*j*j+a[5]*k*k*k,h=hash(t);
for (p=head[h];p!=-1;p=link[p].next)
{
int temp=t+link[p].to;
if (!temp) ++ans;
}
}
printf("%d",ans);
return 0;
}
2002
题意很简单,在平面直角坐标系的整点之间找出正方形的个数
这是一个经典的问题,一般都是用O(n^2)的算法,即枚举两个端点然后hash判断出另外两个点是否存在
这里要用到已知正方形两个顶点坐标找正方形另外两个顶点坐标的公式(画画图证证三角形全等即可):
如果A(x1, y1), B(x2, y2) ,则C(x3, y3),D(x4, y4) 为:
x3=x1+(y1-y2);y3=y1-(x1-x2); (在直线AB上方)
x4=x2+(y1-y2);y4=y2-(x1-x2)
或:
x3=x1-(y1-y2);y3=y1+(x1-x2); (在直线AB下方)
x4=x2-(y1-y2);y4=y2+(x1-x2)
最后ans除个8即可(四条边,两个顶点重复枚举)
CODE
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1005,MAX=80005;
struct node
{
int x,y;
}a[N];
struct edge
{
int to,next;
}link[N];
int n,head[MAX],k,ans;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch=tc(); int flag=1;
while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=tc(); }
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
x*=flag;
}
inline void write(int x)
{
if (x/10) write(x/10);
putchar(x%10+'0');
}
inline int hash(int x,int y)
{
if (x<0) x=-2*x;
if (y<0) y=-2*y;
return x+y;
}
inline void add(int x,int y)
{
link[++k].to=y; link[k].next=head[x]; head[x]=k;
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i,j,p;
for (;;)
{
read(n); k=ans=0;
if (!n) break;
memset(link,-1,sizeof(link));
memset(head,-1,sizeof(head));
for (i=1;i<=n;++i)
{
read(a[i].x); read(a[i].y);
add(hash(a[i].x,a[i].y),i);
}
for (i=1;i<=n;++i)
for (j=1;j<=n;++j)
{
if (i==j) continue;
int x=a[i].x-a[j].x,y=a[i].y-a[j].y,flag=0;
int now1=hash(a[i].x-y,a[i].y+x),now2=hash(a[j].x-y,a[j].y+x);
for (p=head[now1];p!=-1;p=link[p].next)
if (a[link[p].to].x==a[i].x-y&&a[link[p].to].y==a[i].y+x) { ++flag; break; }
for (p=head[now2];p!=-1;p=link[p].next)
if (a[link[p].to].x==a[j].x-y&&a[link[p].to].y==a[j].y+x) { ++flag; break; }
if (flag==2) ++ans; flag=0;
int now3=hash(a[i].x+y,a[i].y-x),now4=hash(a[j].x+y,a[j].y-x);
for (p=head[now3];p!=-1;p=link[p].next)
if (a[link[p].to].x==a[i].x+y&&a[link[p].to].y==a[i].y-x) { ++flag; break; }
for (p=head[now4];p!=-1;p=link[p].next)
if (a[link[p].to].x==a[j].x+y&&a[link[p].to].y==a[j].y-x) { ++flag; break; }
if (flag==2) ++ans; flag=0;
}
write(ans/8); putchar('\n');
}
return 0;
}
2503
垃圾字符串散列问题
读入巨坑,以我的字符串处理技术果不其然的WA了(应该是挂在了读入上)
然后改用字符数组,判断两字符串是否相等只能使用按位比较的方法,果不其然的T了
就想骂人了,突然记起来字符数组也可以扔在map里用(神奇),最后map水过
不过这种类型的问题也可以用字典树来解决,等以后会了再来填坑
CODE
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<map>
using namespace std;
map <string,string> hash;
const int N=100005;
char key[N],s[N];
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
while ((key[0]=getchar())!='\n')
{
scanf("%s%s",key+1,s);
hash[s]=key; getchar();
}
while (scanf("%s",&s)!=EOF)
if (hash.count(s)) cout<<hash[s]<<endl; else puts("eh");
return 0;
}
POJ 3349&&3274&&2151&&1840&&2002&&2503的更多相关文章
- POJ 3349 HASH
题目链接:http://poj.org/problem?id=3349 题意:你可能听说话世界上没有两片相同的雪花,我们定义一个雪花有6个瓣,如果存在有2个雪花相同[雪花是环形的,所以相同可以是旋转过 ...
- POJ 3349:Snowflake Snow Snowflakes(数的Hash)
http://poj.org/problem?id=3349 Snowflake Snow Snowflakes Time Limit: 4000MS Memory Limit: 65536K T ...
- 【POJ】【2151】Check the difficulty of problems
概率DP kuangbin总结中的第8题 一开始题目看错导致想转移方程想错了……想成f[i][j]表示前 i 个队伍中最多的做出来 j 道题的概率……sigh 看了下题解……其实是对于每个队伍 i 单 ...
- POJ 3349 Snowflake Snow Snowflakes(哈希)
http://poj.org/problem?id=3349 题意 :分别给你n片雪花的六个角的长度,让你比较一下这n个雪花有没有相同的. 思路:一开始以为把每一个雪花的六个角的长度sort一下,然后 ...
- POJ 3349 Snowflake Snow Snowflakes Hash
题目链接: http://poj.org/problem?id=3349 #include <stdio.h> #include <string.h> #include < ...
- 【POJ 3349】 Snowflake Snow Snowflakes
[题目链接] http://poj.org/problem?id=3349 [算法] 哈希 若两片雪花相同,则它们六个角上的和一定相同,不妨令 H(A) = sigma(Ai) % P ,每次只要到哈 ...
- [poj 3349] Snowflake Snow Snowflakes 解题报告 (hash表)
题目链接:http://poj.org/problem?id=3349 Description You may have heard that no two snowflakes are alike. ...
- Snowflake Snow Snowflakes POJ - 3349 Hash
题意:一个雪花有六个角 给出N个雪花 判断有没有相同的(可以随意旋转) 参考:https://blog.csdn.net/alongela/article/details/8245005 注意:参考 ...
- 哈希—— POJ 3349 Snowflake Snow Snowflakes
相应POJ题目:点击打开链接 Snowflake Snow Snowflakes Time Limit: 4000MS Memory Limit: 65536K Total Submissions ...
随机推荐
- Android ConstraintLayout详解(from jianshu)
Android ConstraintLayout详解 https://www.jianshu.com/p/a8b49ff64cd3 1. 概述 在本篇文章中,你会学习到有关Constraint ...
- python appium笔记(一):appium android环境配置及示例
(一) 简介 Appium是一个开源的自动化测试框架,可以用来测试基于iOS.Android和Firefox OS平台的原生和混合应用.该框架使用Selenium Webdriver,在执行测试时和 ...
- Bootstrap源码分析系列之整体架构
作为一名合格的前端工程师,你肯定听说过Bootstarp框架.确实可以说Bootstrap框架是最流行的前端框架之一.可是也有人说Bootstrap是给后端和前端小白用的,我认为只要学习它能给我们前端 ...
- Ubuntu 16.04 Server 设置静态IP
一.前言 最近需要在虚拟机当中装个Ubuntu Server 16.04的系统,但是在虚拟机安装的时候,并不像Ubuntu Server 18.04那样能一步步的进行配置,因此导致装好后的虚拟机是动态 ...
- .NET泛型中的协变与逆变
泛型的可变性:协变性和逆变性 实质上,可变性是以一种类型安全的方式,将一个对象作为另一个对象来使用. 我们已经习惯了普通继承中的可变性:例如,若某方法声明返回类型为Stream,在实现时可以返回一个M ...
- 大话存储 3 - 七种磁盘RAID技术
RAID技术 Redundant Array of Independent Disks 由独立的磁盘组成的具有冗余特性的阵列. 有两个特性: 阵列:需要很多磁盘来组成 冗余:允许某块磁盘损坏之后,数据 ...
- 用apiDoc简化接口开发
身为程序员最讨厌看到的代码没有注释,自己的代码却讨厌写注释,觉得麻烦,接口也是这样. 比如公司要做一个H5活动的页面,开发文档已经发到后端开发.设计.与前端的邮箱了,其实这个时候就可以开始开发了.开发 ...
- python + pyqt5 QlineEdit QMessageBox实现信息录入和消息弹框提醒
本人现在在做自动化工具开发的工作,因此,记录下自己平时遇到的问题和解决之道,还有一些简单的小工具 以下为主代码 # --*-- coding:utf-8 --*-- from first import ...
- 使用ramdisk内存分区给常用软件加速
::参考内存盘软件https://download.csdn.net/download/zly6tz/9717137cls @echo off ::内存虚拟盘符-内存盘大小自己查看源目录大小 ::下面 ...
- SQLite简单使用记录
SQLite,一种轻量级的数据库 想要使用的话首先下载安装包. https://www.sqlite.org/download.html 下载sqlite-netFx20-setup-bundle-x ...