SNOI2017(BZOJ5015~5018)泛做
T1:礼物
想错方向了,实际上很简单。
我想的是:显然题目求的是$\sum_{i=1}^{n} i^{k}2^{i}$,然后或许可以通过化式子变成与n无关的复杂度?
然后就不停往斯特林数反演和下降幂的方向想,最后什么都没想出来。
其实想一会就应该意识到:这完全就是一个不可直接化简的式子啊。
$A[i]$表示第$i$个人送的礼物数,$S[i]$为前缀和,那么显然有$S[i]=2*S[i-1]+i^k$,这样就把思路引导矩乘方面去了。
如何矩乘呢?考虑题目的提示。首先$i^k$这个东西不好直接转移到$(i+1)^k$,其次发现转移的话根据二项式定理需要$i^1,i^2,...,i^k$的所有数,最后从题目“$K \leq 10$”可以猜到,一定是将$i^1 i^2 ... i^k$全部扔进矩阵,和$S[i]$一起转移,转移矩阵则正好是$C_i^j$的转置矩阵,这样就可以$O(\log n \times k^3)$解决问题
#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; const ll P=;
ll n,c[][];
int m; struct M{ ll a[][]; M(){ memset(a,,sizeof(a)); } }tr,a1,a2;
M mul(M a,M b){
M c;
rep(i,,m+) rep(j,,m+) rep(k,,m+) c.a[i][k]=(c.a[i][k]+a.a[i][j]*b.a[j][k])%P;
return c;
} M ksm(M a,ll b){
M x=tr;
for (; b; x=mul(x,x),b>>=)
if (b & ) a=mul(a,x);
return a;
} int main(){
scanf("%lld%d",&n,&m);
rep(i,,m) c[i][]=;
rep(i,,m) rep(j,,i) c[i][j]=(c[i-][j-]+c[i-][j])%P;
rep(i,,m){
a1.a[][i]=a2.a[][i]=;
rep(j,,i) tr.a[j][i]=c[i][j];
}
tr.a[m+][m+]=; tr.a[m][m+]=;
a1=ksm(a1,n-); a2=ksm(a2,n);
printf("%lld\n",(a2.a[][m+]-a1.a[][m+]+P)%P);
return ;
}
T2:一个简单的询问
求和上面的无穷符号第一眼有点吓人,实际上就是n。
看数据范围就知道是分块。怎么分?这个虽然简单,但还是有点难想的。$$get(l1,r1,x)\times get(l2,r2,x)$$$$= (get(l1,r1,x)-get(1,l1-1,x)) \times (get(l2,r2,x)-get(1,l2-1,x))$$$$= get(1,r1,x)\times get(1,r2,x)-get(1,r1,x) \times get(1,l2-1,x)-get(1,l1-1,x) \times get(1,r2,x)+get(1,l1-1,x) \times get(1,l2-1,x)$$
这样就可以看出来是莫队了,这里的莫队已经不是传统的$[L,R]$区间询问了,而是真正的曼哈顿最小生成树的替代品。
#include<cmath>
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; const int N=;
ll res[N],ans;
int n,m,a[N],l1,r1,l2,r2,L,R,tot,num1[N],num2[N];
struct Q{ int l,r,k,id,pos; }q[N<<];
bool cmp(Q a,Q b){ return (a.pos==b.pos) ? a.r<b.r : a.pos<b.pos; } int main(){
scanf("%d",&n); int bl=sqrt(n);
rep(i,,n) scanf("%d",&a[i]);
scanf("%d",&m);
rep(i,,m){
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
q[++tot]=(Q){l1-,l2-,,i,(l1-)/bl+}; q[++tot]=(Q){r1,r2,,i,(r1-)/bl+};
q[++tot]=(Q){l1-,r2,-,i,(l1-)/bl+}; q[++tot]=(Q){r1,l2-,-,i,(r1-)/bl+};
}
sort(q+,q+tot+,cmp);
rep(i,,tot){
while (R<q[i].r) ans+=num1[a[++R]],num2[a[R]]++;
while (L>q[i].l) ans-=num2[a[L]],num1[a[L--]]--;
while (R>q[i].r) ans-=num1[a[R]],num2[a[R--]]--;
while (L<q[i].l) ans+=num2[a[++L]],num1[a[L]]++;
res[q[i].id]+=ans*q[i].k;
}
rep(i,,m) printf("%lld\n",res[i]);
return ;
}
T3:炸弹
想不到想不到,线段树的新应用。
首先可以看出是图论,每个炸弹向可以引爆的炸弹连边,强连通块$Tarjan$缩点后建出反图,再按拓扑序跑一遍$DP$计数即可,这是暴力。
发现每个点连出去的所有点一定是一段连续的区间,所以可以想到线段树。所以我们先按照线段树的方法建点连边,这样最后最多只会有$O(n\log n)$个点和$O(n\log n)$条边了。
发现有不少关于区间的问题可以往线段树方面想。
无故$CE$了$5$发,至今未$AC$,改了$cin$和$cout$也过不了,明明没有任何编译错误信息,辣鸡$BZOJ$。
#include<cstdio>
#include<queue>
#include<iostream>
#include<algorithm>
#define ls (x<<1)
#define rs ((x<<1)|1)
#define lson ls,L,mid
#define rson rs,mid+1,R
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; const int N=,M=,mod=;
int scc,n,tim,top,dfn[N],low[N],ind[N],inq[N],stk[N],bel[N],pos[N];
ll ans,a[N],p[N],v[N],Min[N],Max[N],mn[N],mx[N];
queue<int>Q; struct Graph{
int cnt,to[M],nxt[M],h[N];
void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
void tarjan(int x){
dfn[x]=low[x]=++tim; inq[x]=; stk[++top]=x;
for (int i=h[x],k; i; i=nxt[i])
if (!dfn[k=to[i]]) tarjan(k),low[x]=min(low[x],low[k]);
else if (inq[k]) low[x]=min(low[x],dfn[k]);
if (low[x]==dfn[x]){
scc++; int t;
do{
t=stk[top--]; bel[t]=scc; inq[t]=;
Min[scc]=min(Min[scc],mn[t]);
Max[scc]=max(Max[scc],mx[t]);
}while (t!=x);
}
}
}G,G1; void build(int x,int L,int R){
if (L==R) { pos[L]=x; return; }
int mid=(L+R)>>; mn[x]=1ll<<; mx[x]=-(1ll<<);
build(lson); build(rson);
G.add(x,ls); G.add(x,rs);
} void upd(int x,int L,int R,int k,int l,int r){
if (L==l && r==R) { G.add(k,x); return; }
int mid=(L+R)>>;
if (r<=mid) upd(lson,k,l,r);
else if (l>mid) upd(rson,k,l,r);
else upd(lson,k,l,mid),upd(rson,k,mid+,r);
} int main(){
freopen("bzoj5017.in","r",stdin);
freopen("bzoj5017.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n; build(,,n);
rep(i,,n) cin>>a[i]>>v[i],mn[pos[i]]=mx[pos[i]]=a[i];
a[n+]=1ll<<;
rep(i,,n){
int l=lower_bound(a+,a+n+,a[i]-v[i])-a;
int r=upper_bound(a+,a+n+,a[i]+v[i])-a-;
upd(,,n,pos[i],l,r);
}
rep(i,,n<<) if (!dfn[i]) G.tarjan(i);
rep(x,,n<<) for (int i=G.h[x],k; i; i=G.nxt[i])
if (bel[x]!=bel[k=G.to[i]]) G1.add(bel[k],bel[x]),ind[bel[x]]++;
rep(i,,scc) if (!ind[i]) Q.push(i);
while (!Q.empty()){
int x=Q.front(); Q.pop();
for (int i=G1.h[x],k; i; i=G1.nxt[i]){
ind[k=G1.to[i]]--; Min[k]=min(Min[k],Min[x]),Max[k]=max(Max[k],Max[x]);
if (!ind[k]) Q.push(k);
}
}
rep(i,,n){
int r=upper_bound(a+,a+n+,Max[bel[pos[i]]])-a;
int l=lower_bound(a+,a+n+,Min[bel[pos[i]]])-a;
ans=(ans+1ll*(r-l)*i)%mod;
}
cout<<ans<<endl;
return ;
}
T4:英雄联盟。
一眼想出暴力做法,发现连暴力分都拿不到,然后就不会了。
一看题解,发现暴力就是正解,十分崩溃。
$f[i][j]$表示前$i$个英雄花$j$元所能得到的最多方案数,直接转移,普及组难度。
可能会爆$long long$,所以所有大于$m$的都记成等于就好了。
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; ll f[][],m,t;
int n,c[],k[]; int main(){
scanf("%d%lld",&n,&m);
rep(i,,n) scanf("%d",&k[i]);
rep(i,,n) scanf("%d",&c[i]);
f[][]=;
rep(i,,n){
rep(j,,t) f[i][j]=f[i-][j];
rep(j,,k[i]) rep(l,c[i]*j,t+c[i]*j)
f[i][l]=min(m,max(f[i][l],(ll)f[i-][l-j*c[i]]*j));
t+=c[i]*k[i];
}
rep(i,,t) if(f[n][i]>=m) { printf("%d\n",i); return ; }
return ;
}
SNOI2017(BZOJ5015~5018)泛做的更多相关文章
- codeforces泛做..
前面说点什么.. 为了完成日常积累,傻逼呵呵的我决定来一发codeforces 挑水题 泛做.. 嗯对,就是泛做.. 主要就是把codeforces Div.1的ABCD都尝试一下吧0.0.. 挖坑0 ...
- 学记笔记 $\times$ 巩固 · 期望泛做$Junior$
最近泛做了期望的相关题目,大概\(Luogu\)上提供的比较简单的题都做了吧\(233\) 好吧其实是好几天之前做的了,不过因为太颓废一直没有整理-- \(Task1\) 期望的定义 在概率论和统计学 ...
- 历年NOIP水题泛做
快noip了就乱做一下历年的noip题目咯.. noip2014 飞扬的小鸟 其实这道题并不是很难,但是就有点难搞 听说男神错了一个小时.. 就是$f_{i,j}$表示在第$i$个位置高度为$j$的时 ...
- HAOI2015 泛做
T1 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白色.将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间的 ...
- LCT裸题泛做
①洞穴勘测 bzoj2049 题意:由若干个操作,每次加入/删除两点间的一条边,询问某两点是否连通.保证任意时刻图都是一个森林.(两点之间至多只有一条路径) 这就是个link+cut+find roo ...
- 基尔霍夫矩阵题目泛做(AD第二轮)
题目1: SPOJ 2832 题目大意: 求一个矩阵行列式模一个数P后的值.p不一定是质数. 算法讨论: 因为有除法而且p不一定是质数,不一定有逆元,所以我们用辗转相除法. #include < ...
- 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做
题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...
- FFT与多项式、生成函数题目泛做
题目1 COGS 很强的乘法问题 高精度乘法用FFT加速 #include <cstdlib> #include <iostream> #include <algorit ...
- 二维计算几何基础题目泛做(SYX第一轮)
题目1: POJ 2318 TOYS 题目大意: 给一个有n个挡板的盒子,从左到右空格编号为0...n.有好多玩具,问每个玩具在哪个空格里面. 算法讨论: 直接叉积判断就可以.注意在盒子的边界上面也算 ...
随机推荐
- 使用abp的 redis cache
top 使用abp的 redis cache -1. 在微软维护的github项目的release里找到redis的windows版本 64位 大约5M,安装,安装,然后在安装目录找到redis.wi ...
- Centos服务器ssh免密登录以及搭建私有git服务器
一.概述 服务器的免密登录和git服务器的搭建,关键都是要学会把自己用的机器的公钥添加到服务器上,让服务器“认识”你的电脑,从而不需要输入密码就可以远程登录服务器上的用户 免密登录当然是登录root用 ...
- hdu 1213 How Many Tables(并查集算法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1213 How Many Tables Time Limit: 2000/1000 MS (Java/O ...
- 64_l4
libnormaliz-devel-3.1.4-2.fc26.i686.rpm 23-May-2017 00:24 31214 libnormaliz-devel-3.1.4-2.fc26.x86_6 ...
- golang锁记
golang中有两个锁实现 atomic的CAS实现锁 首先是inter cpu,熟悉汇编的人都知道,inter指令集有个lock,如果某个指令集前面加个lock,那么在多核状态下,某个核执行到这个前 ...
- java实现数据库分页
/*** * 工具类 * @param pageIndex //页码 * @param pageSize//每页数据的条数 * @param rowCount//总的数据条数 * @return */ ...
- pxe+kickstart自动化安装
什么是PXE? PXE(Pre-boot Execution Environment,预启动执行环境)是Intel公司开发的最新技术,工作于Client/Server模式.PXE是一种远程引导方式,要 ...
- 小程序 image跟view标签上下会有空隙
解决方案 就是可以在image那里设置vertical-align:top/bottom/text-top/text-bottom 原因:图片文字等inline元素默许是跟父级元素的baseline对 ...
- redis之(六)redis的列表类型的命令
[一]向列表两端添加元素 -->命令:LPUSH key value [value ...] -->向列表的左侧添加元素,返回值表示增加元素后列表的长度 -->命令:RPUSH ke ...
- 通过IP地址和子网掩码计算主机数
知道ip地址和子网掩码后可以算出: 1. 网络地址 2. 广播地址 3. 地址范围 4. 本网有几台主机 例1:下面例子IP地址为192·168·100·5 子网掩码是255·255·255·0.算出 ...