题意:
给定的三个由'0','1','2','3','?'构成的字符串A,B,C。其中'?'表示该位可能是0,1,2,3,现在如果有三个四进制的数依次是这三个字符串,若有A+B=C,则称[A,B,C]是这三个字符串的一组解,现在给定A,B,C,求解的个数。
题解 1:
搜索:一开始觉的就是用搜索的办法枚举 a和b的所有情况然后和c比较;这个想法是对的,但怎么实现呢,一开是以为将 a,b分别放到两个数组里 分别搜索,但是 怎么搜啊,两个数组
后来想到 ,将a和b 存到一个数组里面,前六位存a 从第七为开始 存b (首先要使a,b倒置,再存),然后搜索就可以了;
View Code
#include<stdio.h> #include<string.h> #define inf 9999999 #define maxn 10 int ans; char a[maxn*2],b[maxn],c[maxn]; int na[maxn*2],nb[maxn],nc[maxn],num[maxn*2]; void DFS(int x) { int i; if(x>=12) { for(i=0;i<7;i++)num[i]=0; for(i=0;i<6;i++) { num[i]+=na[i]+na[i+6]; num[i+1]+=num[i]/4; num[i]=num[i]%4; } for(i=0;i<7;i++) { if(nc[i]!=num[i]&&nc[i]!=-1) { return ; } } ans++; return ; } if(na[x]==-1) { for(i=0;i<4;i++) { na[x]=i; DFS(x+1); }na[x]=-1; } else DFS(x+1); } int main() { int i; while(scanf("%s%s%s",a,b,c)!=EOF) { memset(na,0,sizeof(na)); memset(num,0,sizeof(num)); memset(na,0,sizeof(na)); memset(nb,0,sizeof(nb)); memset(nc,0,sizeof(nc)); int len=strlen(a); for(i=0;i<len;i++) { if(a[len-1-i]!='?') na[i]=a[len-1-i]-'0'; else na[i]=-1; } len=strlen(b); for(i=0;i<len;i++) { if(b[len-1-i]!='?') na[i+6]=b[len-1-i]-'0'; else na[i+6]=-1; } len=strlen(c); for(i=0;i<strlen(c);i++) { if(c[len-1-i]!='?') nc[i]=c[len-1-i]-'0'; else nc[i]=-1; } ans=0; DFS(0); printf("%d\n",ans); } }
题解2:
运用dp
因为到达以为时无非有两种情况, 有进位,没进位
dp[i][0]表示前i位,第i位没有进位时,有多少中
dp[i][1]表示前i位,第i位有进位时,有多少种
View Code
1002:题意 想必大家已经知道如何建立二叉排序树了吧.二叉排序树的介绍如链接所示 http://baike.baidu.com/view/922220.htm
例如依次给出9个正整数:8 ,3, 10, 1, 6, 14 ,4 ,7 ,13,建立后的二叉排序树如下图所示.
现在依次给出N个不同的正整数,每个数都不大于10^9,利用这N个有顺序的正整数可以建立出一颗二叉排序树.对于建成的这颗二叉排序树,询问某个节点的祖父节点的值(若该节点没有祖父节点则输出-1).
例如依次给出9个正整数:8 ,3, 10, 1, 6, 14 ,4 ,7 ,13,建立后的二叉排序树如下图所示.
现在依次给出N个不同的正整数,每个数都不大于10^9,利用这N个有顺序的正整数可以建立出一颗二叉排序树.对于建成的这颗二叉排序树,询问某个节点的祖父节点的值(若该节点没有祖父节点则输出-1).
一般的二叉排序树建图的话,会超时,这里用的了另一种高级的数据结构 笛卡尔树 ,迪卡而数和treap 基本上一样支部过时,他的alue值是预先设定好的,
介绍“:
笛卡尔树又称笛卡儿树,在数据结构中属于二叉树的一种。 笛卡尔树结构由Vuillmin在解决范围搜索的几何数据结构问题时提出的,从数列中构造一棵 笛卡尔树可以线性时间完成,需要采用基于栈的算法来找到在该数列中的所有最近小数。由此可知,笛卡尔树是一种特定的二叉树数据结构,可由数列构造,在范围 最值查询、范围top k查询(range top k queries)等问题上有广泛应用。它具有堆的有序性,中序遍历可以输出原数列。 可以这么说:笛卡尔树是一棵二叉树,树的每个节点有两个值,一个为key,一个为value。 光看key的话,笛卡尔树是一棵二叉搜索树,每个节点的左子树的key都比它小,右子树都比它大;光看value的话,笛卡尔树有点类似堆,根节点的 value是最小(或者最大)的,每个节点的value都比它的子树要大
题解:
View Code
#include <iostream> #include<stdio.h> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <ctime> #include <queue> #include <map> #include <sstream> #include<stdlib.h> #include<stdio.h> #define CL(a,num) memset(a,num,sizeof(a)) #define MIN(a,b) a>b?b:a #define MAX(a,b) a>b?a:b #define maxn 50010 using namespace std; map<int ,int >map1; int n,m; struct node { int k,val; int lc,rc,pre; }p[maxn]; int cmp( const void *a ,const void *b) { return (*(node *)a).k > (*(node *)b).k ? 1 : -1; } void build_tree() { int i,k; p[0].rc=1; k=1; for(i=2;i<=n;i++) { while(p[k].val>p[i].val)k=p[k].pre;//每一次找到第一个比他val小的,因为先排序处理了,所以肯定是沿着 右边插入 p[i].lc=p[k].rc; p[p[k].rc].pre=i; p[k].rc=i; p[i].pre=k; k=i;//注意这, } } int main() { int i; while(scanf("%d%d",&n,&m)!=EOF) { map1.clear(); for(i=0;i<=n;i++) { p[i].pre=p[i].k=p[i].val=p[i].lc=p[i].rc=0; } for(i=1;i<=n;i++) { scanf("%d",&p[i].k); p[i].val=i; } qsort(p+1,n,sizeof(p[0]),cmp); for(i=1;i<=n;i++) { map1[p[i].k]=i; } build_tree(); int q,a; while(m--) { scanf("%d",&q); a=map1[q]; if(p[a].pre==0){printf("-1\n");continue;} a=p[a].pre; if(p[a].pre==0){printf("-1\n");continue;} printf("%d\n",p[p[a].pre].k); } } }