(今天兴致大发学了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的更多相关文章

  1. POJ 3349 HASH

    题目链接:http://poj.org/problem?id=3349 题意:你可能听说话世界上没有两片相同的雪花,我们定义一个雪花有6个瓣,如果存在有2个雪花相同[雪花是环形的,所以相同可以是旋转过 ...

  2. POJ 3349:Snowflake Snow Snowflakes(数的Hash)

    http://poj.org/problem?id=3349 Snowflake Snow Snowflakes Time Limit: 4000MS   Memory Limit: 65536K T ...

  3. 【POJ】【2151】Check the difficulty of problems

    概率DP kuangbin总结中的第8题 一开始题目看错导致想转移方程想错了……想成f[i][j]表示前 i 个队伍中最多的做出来 j 道题的概率……sigh 看了下题解……其实是对于每个队伍 i 单 ...

  4. POJ 3349 Snowflake Snow Snowflakes(哈希)

    http://poj.org/problem?id=3349 题意 :分别给你n片雪花的六个角的长度,让你比较一下这n个雪花有没有相同的. 思路:一开始以为把每一个雪花的六个角的长度sort一下,然后 ...

  5. POJ 3349 Snowflake Snow Snowflakes Hash

    题目链接: http://poj.org/problem?id=3349 #include <stdio.h> #include <string.h> #include < ...

  6. 【POJ 3349】 Snowflake Snow Snowflakes

    [题目链接] http://poj.org/problem?id=3349 [算法] 哈希 若两片雪花相同,则它们六个角上的和一定相同,不妨令 H(A) = sigma(Ai) % P ,每次只要到哈 ...

  7. [poj 3349] Snowflake Snow Snowflakes 解题报告 (hash表)

    题目链接:http://poj.org/problem?id=3349 Description You may have heard that no two snowflakes are alike. ...

  8. Snowflake Snow Snowflakes POJ - 3349 Hash

    题意:一个雪花有六个角  给出N个雪花 判断有没有相同的(可以随意旋转) 参考:https://blog.csdn.net/alongela/article/details/8245005 注意:参考 ...

  9. 哈希—— POJ 3349 Snowflake Snow Snowflakes

    相应POJ题目:点击打开链接 Snowflake Snow Snowflakes Time Limit: 4000MS   Memory Limit: 65536K Total Submissions ...

随机推荐

  1. Expo大作战(三)--针对已经开发过react native项目开发人员有针对性的介绍了expo,expo的局限性,开发时项目选型注意点等

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  2. 【python】python中的json、字典dict

    定义 python中,json和dict非常类似,都是key-value的形式,而且json.dict也可以非常方便的通过dumps.loads互转.既然都是key-value格式,为啥还需要进行格式 ...

  3. 《SQLSERVER2012实施与管理实战指南》前4章节笔记内容

    <SQLSERVER2012实施与管理实战指南>前4章节笔记内容 <SQLSERVER2012实施与管理实战指南>的前面4章是<SQLSERVER企业级平台管理实践> ...

  4. 《SQL Server 2008从入门到精通》--20180723

    目录 1.架构 1.1.创建架构并在架构中创建表 1.2.删除架构 1.3.修改表的架构 2.视图 2.1.新建视图 2.2.使用视图修改数据 2.3.删除视图 3.索引 3.1.聚集索引 3.2.非 ...

  5. Windows DHCP备份还原命令

    DHCP服务器如果要更换,最简单的方法就是命令导入导出   导出netsh dhcp server export e:\dhcp.txt all 导入netsh dhcp server import ...

  6. python os模块 遍历目录

    #os #os ->tree命令 import os #递归 #目录 ->文件,文件夹 -> 文件文件夹 dirpath = input('请输入你要遍历的目录\n') def ge ...

  7. 【转】Spring学习---Bean配置的三种方式(XML、注解、Java类)介绍与对比

    [原文]https://www.toutiao.com/i6594205115605844493/ Spring学习Bean配置的三种方式(XML.注解.Java类)介绍与对比 本文将详细介绍Spri ...

  8. MySQL基础之 恢复数据和数据库迁移

    1.mysql命令或者source命令恢复数据 这两个命令在进行恢复数据的时候要检查是否创建数据库.如果数据库不存在,则恢复失败. 数据库迁移 1.相同版本的mysql数据库之间的迁移. mysqld ...

  9. 阿里云 IOT 对接设备开发 C# 开发设备对接阿里云 IOT平台

    一,创建阿里云 IOT 产品.设备 目前阿里云每月赠送 100 万条流量,可以免费使用基础版.高级版,开通后即可免费使用. 阿里云 IOT 平台地址 https://iot.console.aliyu ...

  10. November 02nd, 2017 Week 44th Thursday

    Knowledge is weightless, a treasure you can always carry easily. 知识没有重量,她是我们可以很容易携带的珍宝. Knowledge is ...