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 ...
随机推荐
- autocad视图汇报,像ppt那样汇报
在大部分场景中,工程师可以用cad进行汇报,避免去做PPT,浪费时间,ppt一般都是用一次就丢弃.而工程师对于设计的中间汇报,或三维bim汇报,评审汇报,展示汇报等,都可以直接用cad软件,方法是用视 ...
- GridLayout和GridView的区别
GridView是一种适配器布局,它的继承关系是ViewGroup-->AdapterView-->AbsListView-->GridView,他是从一个adapter中取出内容填 ...
- react native中Unable to load script from assets 'index.android.bundle'解决方案
刚刚朋友问我,说是创建好一个项目,运行后报错:Unable to load script from assets 'index.android.bundle',以前好好的没出现这种现象,于是我找到一个 ...
- 3hibernate核心对象关系映射 xxx.hbm.xml
Hibernate的核心就是对象关系映射: 加载映射文件的两种方式: 第一种:<mapping resource="com/bie/lesson02/crud/po/employee. ...
- SQLSERVER NULL和空字符串的区别 使用NULL是否节省空间
SQLSERVER NULL和空字符串的区别 使用NULL是否节省空间 这里只讨论字符串类型,int.datetime.text这些数据类型就不讨论了,因为是否节省空间是根据数据类型来定的 在写这篇文 ...
- nopcommerce
nopcommerce是国外的一个高质量的开源b2c网站系统,基于EntityFramework4.0和MVC3.0,使用Razor模板引擎,有很强的插件机制,包括支付配送功能都是通过插件来实现的,基 ...
- SQL Server中数据库文件的存放方式,文件和文件组 (转载)
简介 在SQL SERVER中,数据库在硬盘上的存储方式和普通文件在Windows中的存储方式没有什么不同,仅仅是几个文件而已.SQL SERVER通过管理逻辑上的文件组的方式来管理文件.理解文件和文 ...
- MySQL innodb中各种SQL语句加锁分析
概要 Locking read( SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE),UPDATE以及DELETE语句通常会在他扫描的索引所 ...
- ln -s 软连接介绍
软连接(softlink)也称符号链接.linux里的软连接文件就类似于windows系统中的快捷方式.软连接文件实际上是一个特殊的文件,文件类型是I.软连接文件实际上可以理解为一个文本文件,这个文件 ...
- 使用Swoole 构建API接口服务
网上类似的文章已经很多了,我也是刚入门.从头开始学习.所以如果重复写文章阐释,反而会浪费时间,于是就自己动手构建了一个demo,使用swoole 的TCP 服务器接受TCP客户端的发来的http请求, ...