(今天兴致大发学了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. Adobe Flash Builder 4.6 打开时提示Failed to create the Java Virtual Machine

    最近使用actionscript来编程,用到Adobe Flash Builder 工具,之前一直用着都没事的,今天打开突然就报了这个错误,然后就打不开了 好了,不多说,直接来吧. 首先在你的Adob ...

  2. Android应用程序进程启动过程(后篇)

    前言 在前篇中我们讲到了Android应用程序进程启动过程,这一篇我们来讲遗留的知识点:在应用程序进程创建过程中会启动Binder线程池以及在应用程序进程启动后会创建消息循环. 1.Binder线程池 ...

  3. mysql内存管理

    1 内存管理结构 mysql有自己的内存申请和释放机制 mysql层有mem_root innodb层有mem_heap,mem_pool,buf_pool 它们的结构图如下 2 mem_root m ...

  4. 使用Eclipse Debug的一些说明

    目录 Debug视图 线程堆栈视图 变量视图 断点视图 表达式视图 代码视图 远程Debug 异常断点 条件断点 表达式 Debug定位第三方插件的问题 Debug一些经验   Debug视图 认识d ...

  5. BAT文件语法和技巧

    首先,批处理文件是一个文本文件,这个文件的每一行都是一条DOS命令(大部分时候就好象我们在DOS提示符下执行的命令行一样),你可以使用DOS下的Edit或者Windows的记事本(notepad)等任 ...

  6. Linux磁盘空间占满问题快速定位

    1.df -h命令查看系统盘与各个磁盘的占用空间比率 [tidb@:vg_adn_tidbCkhsTest:172.31.30.62 /dev]$df -Th Filesystem Type Size ...

  7. 团队作业——Alpha冲刺 4/12

    团队作业--Alpha冲刺 冲刺任务安排 杨光海天 今日任务:着手进行编辑界面的布局,插入控件,并进行参数调整. 明日任务:继续完善编辑界面控件,学习控件交互功能. 郭剑南 今日任务:上网查阅学习了关 ...

  8. chrome主页被篡改为360导航之解决方式

    昨天,安装某款游戏之后,发现chrome的主页被篡改为360导航. 进入chrome设置改动主页,又一次启动chrome还是360导航,后来发如今chrome快捷方式的属性中目标后面加了一串360导航 ...

  9. HTTP 请求头中的 X-Forwarded-For,X-Real-IP

     X-Forwarded-For 在使用nginx做反向代理时,我们为了记录整个的代理过程,我们往往会在配置文件中做如下配置: location / { 省略... proxy_set_header ...

  10. 【转】Android中通知的提示音、震动和LED灯效果小例子

    通知(Notification)是 Android 系统中比较有特色的一个功能,当某个应用程序希望向用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知来实现.发出一条通知后,手机最上方 ...