17.8.27 校内赛 解题报告【卢卡斯定理】【dfs+hash】【线段树】
2017-08-27 17:17
411 查看
1.crf 出生的第一秒
解题报告
这道题显然是裸的卢卡斯定理,p还是质数。注意要开long long。代码如下:
2.crf 出生的第二秒
解题报告
这道题是的一种做法是把一棵树拿来hash(dfs),获得一个hash值。询问的时候把询问的那棵树hash值算出来再去map里面查询就行了。
3.crf 出生的第三秒
解题报告
这道题因为只有7种数字,用线段树维护每一段的7种数字分别有多少,合并就行了。
以上
解题报告
这道题显然是裸的卢卡斯定理,p还是质数。注意要开long long。代码如下:
#include<cmath> #include<cstdio> #include<algorithm> #define NAME "first" #define ll long long using namespace std; const int P=100000; int n,m,mod; ll jie[P+5]; ll qmul(ll a,ll b)//快速乘 { int rt; for(rt=0;b;b>>=1,a=(a%mod+a%mod)%mod) if(b&1)rt=(rt%mod+a%mod)%mod; return rt; } ll qpow(ll a,ll b)//快速幂 { int rt; for(rt=1;b;b>>=1,a=qmul(a,a)) if(b&1)rt=qmul(rt,a); return rt; } ll C(ll n,ll m) { if(m>n)return 0; if(n<mod)return qmul(qmul(jie ,qpow(jie[m],mod-2)%mod),qpow(jie[n-m],mod-2)%mod);//没有到mod就套公式 return qmul(C(n/mod,m/mod),C(n%mod,m%mod));//过了mod就用卢卡斯定理 } int main() { freopen(NAME".in","r",stdin); freopen(NAME".out","w",stdout); scanf("%d%d%d",&n,&m,&mod); jie[0]=1; for(int i=1;i<=mod-1;i++)jie[i]=qmul((ll)i,jie[i-1]);//预处理阶乘 printf("%I64d",C((ll)n,(ll)m)); return 0; }
2.crf 出生的第二秒
解题报告
这道题是的一种做法是把一棵树拿来hash(dfs),获得一个hash值。询问的时候把询问的那棵树hash值算出来再去map里面查询就行了。
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #define NAME "second" using namespace std; const int N=100000 ; unsigned long long base1[N+5]={1},base2[N+5]={1}; unsigned long long dpp1[N+5]={1},dpp2[N+5]={1},hash1,hash2; map<unsigned long long,int>list_1,list_2; struct edge { int v,next; }ed[N+5]; int n,m,q,head[N+5],siz[N+5],in[N+5],num; void build(int u,int v) { in[v]++; ed[++num].v=v ; ed[num].next=head[u] ; head[u]=num ; } void dfs(int u,int dep) { siz[u]=1; for(int i=head[u];i!=-1;i=ed[i].next) { dfs(ed[i].v,dep+1) ; siz[u]+=siz[ed[i].v] ; } hash1+=base1[siz[u]]*dpp1[dep] ; hash2+=base2[siz[u]]*dpp2[dep] ; } void clear() { num=0;hash1=hash2=0; memset(in,0,(m+1)*sizeof(int)); memset(head,-1,(m+1)*sizeof(int)); memset(siz,0,(m+1)*sizeof(int)); } int main() { freopen(NAME".in","r",stdin); freopen(NAME".out","w",stdout); scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=m;i++)base1[i]=base1[i-1]*73U,base2[i]=base2[i-1]*47U,dpp1[i]=dpp1[i-1]*193U,dpp2[i]=dpp2[i-1]*233U; for(int i=1;i<=n;i++) { clear(); for(int j=1;j<=m-1;j++) { int u,v; scanf("%d%d",&u,&v); build(u,v) ; } for(int j=1;j<=m;j++)if(!in[j]){dfs(j,1);break;} list_1[hash1]++; list_2[hash2]++; } for(int i=1;i<=q;i++) { clear(); for(int j=1;j<=m-1;j++) { int u,v; scanf("%d%d",&u,&v); build(u,v); } for(int j=1;j<=m;j++)if(!in[j]){dfs(j,1);break;} int t1=list_1[hash1],t2=list_2[hash2]; printf("%d\n",min(t1,t2)); } return 0; }
3.crf 出生的第三秒
解题报告
这道题因为只有7种数字,用线段树维护每一段的7种数字分别有多少,合并就行了。
#include<cstdio> #include<iostream> #include<cstring> const int maxn=100010; struct Node { int cnt[7]; int size; int cover; Node() { memset(cnt,0,sizeof(cnt)); cover=-1; } inline void set(int cover) { this->cover=cover; for(int i=0;i<7;i++) if(i==cover)cnt[i]=size; else cnt[i]=0; } inline friend Node operator+(const Node &a,const Node &b) { Node c; for(int i=0;i<7;i++)c.cnt[i]=a.cnt[i]+b.cnt[i]; return c; } }t[maxn<<2]; int a[maxn]; inline void update(int rt) { t[rt].size=t[rt<<1].size+t[rt<<1|1].size; for(int i=0;i<7;i++)t[rt].cnt[i]=t[rt<<1].cnt[i]+t[rt<<1|1].cnt[i]; } inline void pushdown(int rt) { if(t[rt].cover!=-1) { t[rt<<1].set(t[rt].cover); t[rt<<1|1].set(t[rt].cover); t[rt].cover=-1; } } inline void build(int l,int r,int rt) { if(l==r) { t[rt].size=1; t[rt].cnt[a[l]]=1; return; } int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); update(rt); } inline Node query(int l,int r,int rt,int L,int R) { if(l>=L&&r<=R)return t[rt]; pushdown(rt); int mid=(l+r)>>1; Node answer; if(L<=mid)answer=answer+query(l,mid,rt<<1,L,R); if(R>mid)answer=answer+query(mid+1,r,rt<<1|1,L,R); return answer; } inline void change(int l,int r,int rt,int L,int R,int cover) { if(l>=L&&r<=R) { t[rt].set(cover); return; } pushdown(rt); int mid=(l+r)>>1; if(L<=mid)change(l,mid,rt<<1,L,R,cover); if(R>mid)change(mid+1,r,rt<<1|1,L,R,cover); update(rt); } int main() { freopen("third.in","r",stdin); freopen("third.out","w",stdout); int n,q; scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); a[i]--; } build(1,n,1); for(int i=1;i<=q;i++) { int l,r,opt; scanf("%d%d%d",&l,&r,&opt); Node answer=query(1,n,1,l,r); int nowl=l; if(opt==0) { for(int j=0;j<7;j++) if(answer.cnt[j]) { change(1,n,1,nowl,nowl+answer.cnt[j]-1,j); nowl+=answer.cnt[j]; } } else { for(int j=6;j>=0;j--) if(answer.cnt[j]) { change(1,n,1,nowl,nowl+answer.cnt[j]-1,j); nowl+=answer.cnt[j]; } } } for(int i=1;i<=n;i++) { Node answer=query(1,n,1,i,i); int x=-1; for(int j=0;j<7;j++)if(answer.cnt[j])x=j+1; printf("%d%c",x,i==n?'\n':' '); } return 0; }
以上
相关文章推荐
- 校内赛 2017.8.27 【卢卡斯定理】 【DFS+Hash】【线段树】
- Hdu 3037 Saving Beans 卢卡斯定理 解题报告
- 2018.1.29【 HDU - 1518 】解题报告(dfs,极易TLE,剪枝)
- 校内赛 codeforces 827D【最小生成树】【树链剖分】 解题报告
- 【解题报告】POJ1151 扫描线+线段树(矩形求并)
- Polya 定理 (附POJ 1286 Necklace of Beads 解题报告)
- codevs 1047 邮票面值设计 DFS+DP 解题报告
- 解题报告:POJ 1753 Flip Game 简单深搜dfs
- Hdu 1754 I Hate It 线段树 解题报告
- 【解题报告】 NYOJ 116 士兵杀敌(二) 线段树 单点更新求区间和
- poj2488 DFS马棋环游 解题报告
- HDU 4578 Transformation 解题报告(线段树,2013杭州邀请赛)
- 解题报告:线段树的修改
- CodeVS1690 开关灯 解题报告【数据结构】【线段树】
- 简单典型DFS---(解题报告)HDU1312---Red and Black
- 2018.3.1【 HDU - 6113 】解题报告(百度之星初赛,BFS,DFS,图像处理)
- HDU 1892 See you~ 解题报告(线段树版)
- 线段树 查询删除 后序遍历 POJ2182 Lost Cows解题报告
- POJ1190 生日蛋糕 ACM解题报告(DFS回溯+剪枝)
- HDU1556 Color the ball 解题报告--线段树