2017北京国庆刷题Day5 morning
期望得分:0+60+60=120
实际得分:0+30+60=90
令g=gcd(X11,X12,X13……)
则行列式可能为D的充要条件为g|D
1、g|D为必要条件:
由定义来算行列式的时候,每一项都要从第一行里取一个数,所以g|D
2、g|D为充分条件:
首先可以通过矩阵的初等变换,将矩阵X消成对角矩阵
其中,X11* X22 * X33* X44=D
上述矩阵等价于
把D拆为g*D/g
还原到矩阵中
即
X22=
此矩阵模拟先前初等变换即可还原为原矩阵X
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath> using namespace std; int gcd(int a,int b) { return !b ? a : gcd(b,a%b); } bool solve()
{
int n,m,x,y;
scanf("%d%d",&n,&m);
x=;
for (int i=;i<=n;++i)
{
scanf("%d",&y);
x=gcd(x,abs(y));
}
if (n==) return y==m;
if (!x) return !m;
return !(abs(m)%x);
} int main()
{
freopen("det.in","r",stdin);
freopen("det.out","w",stdout);
int t;
scanf("%d", &t);
while(t--)
if (solve()) printf("Y\n");
else printf("N\n");
}
每次分两半的时候,一定是奇数在左边,偶数在右边
所以用类似于线段树的思想来分治
由于每次讲将序列按奇偶下标分成两半,如果每次处理分成的那一半区间
那这个区间一定是一个等差数列,且公差为 2^d
所以
如果我们将区间离散化为1,2,3,……
那么完全可以求出区间离散化之后的答案,在回溯往上的时候每次*2(奇数*2-1),便可得到原区间的答案
例:1 2 3 4 5 6 7
第一次分治:
原左区间: 1 3 5 7 原右区间 2 4 6
离散化后区间 1 2 3 4 1 2 3
离散化后左区间 总和 1+2+3+4=10
当回溯到上一层是,实际上是(1*2-1)+(2*2-1)+(3*2-1)+(4*2-1)= 10*2-4=16
离散化后右区间 总和 1+2+3=6
当回溯到上一层是,实际上是 (1*2)+(2*2)+(3*2)=6*2=12
具体怎么求?
设当前分治到 rr,l,r,x,y
表示当前区间离散化后为[1,2,……rr],当前要求下标在本区间的[l,r]内,大小 在 本区间离散化后[x,y]之间
分四种情况:
1、对答案有贡献的数全在当前区间内,即 l=1 && r=rr
因为每次分治的区间是一个等差数列,根据求和公式,本区间的答案为(y-x+1)*(x+y)/2
2、对答案有贡献的数是当前区间的一部分且全在左区间,即r<=mid ,那就递归到左区间求解
在左区间中 ,rr变成mid,l,r 不变,x变为x/2+1,y变为(y+1)/2
3、对答案有贡献的数是当前区间的一部分且全在右区间,即l>mid,那就递归到右区间求解
在右区间中,rr变成rr-mid,l-=mid,r-=mid,x变为(x+1)/2,y变为y/2+1
4、对答案有贡献的数是当前区间的一部分且左右区间都有,左右区间都递归,再合并
这里 l,r 根上面的左右区间有所不同
左区间的r是mid,右区间的l是1
上面提到了左区间是奇数,回溯的时候 和变为*2-元素个数
所以 回溯时,除了返回 和,还要返回元素个数
用pair即可
小细节:等差数列求和的时候,(y-x+1)*(x+y)/2 乘法运算可能会爆long long
所以 判断哪个是偶数,先进行除法运算
#include<cstdio>
#include<iostream> #define mp(a,b) make_pair((a),(b)) using namespace std; typedef long long LL;
typedef pair<LL,LL>pr; LL mod; void read(LL &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} pr solve(LL rr,LL l,LL r,LL x,LL y)
{
if(x>rr || l>r) return mp(,);
if(l== && r==rr)
{
y=min(y,rr);
LL s;
if (!((x+y)&))s=(x+y>>)%mod*((y-x+)%mod)%mod;
else s=((x+y)%mod)*((y-x+>>)%mod)%mod;
return mp(s,(y-x+)%mod);
}
LL mid=rr+>>;
if(r<=mid)
{
pr res=solve(mid,l,r,(x>>)+,y+>>);
return mp(((res.first<<)-res.second)%mod,res.second);
}
if(l>mid)
{
pr res=solve(rr-mid,l-mid,r-mid,x+>>,y>>);
return mp((res.first<<)%mod,res.second);
}
pr res1=solve(mid,l,mid,(x>>)+,y+>>);
pr res2=solve(rr-mid,,r-mid,x+>>,y>>);
return mp(((res1.first<<)-res1.second+(res2.first<<))%mod,(res1.second+res2.second)%mod);
} int main()
{
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
LL n,m;
read(n); read(m); read(mod);
LL l,r,x,y;
while(m--)
{
read(l); read(r); read(x); read(y);
pr ans=solve(n,l,r,x,y);
printf("%I64d\n",(ans.first+mod)%mod);
}
}
考场 30分 莫队 ,然而枚举有60
#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 100001
#define lowbit(x) x&(-x)
using namespace std;
typedef long long LL;
int a[N],n,m,mod;
int bl[N];
LL c[N],ans[N];
struct node
{
int l,r,x,y,id;
}e[N];
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void dfs(int l,int r,int k)
{
if(l==r) return;
int m=l+r>>,t=m;
dfs(l,m,k<<);
for(int i=l;i<=m;i++) if(a[i]+k<=n) a[++t]=a[i]+k;
}
bool cmp(node p,node q)
{
if(bl[p.l]!=bl[q.l]) return bl[p.l]<bl[q.l];
return p.r<q.r;
}
void add(int x,int w)
{
while(x<=n) { c[x]+=w; x+=lowbit(x); }
}
LL query(int x)
{
LL sum=;
while(x) { sum+=c[x]; x-=lowbit(x); }
return sum;
}
void update(int pos,bool ty)
{
if(ty) add(a[pos],a[pos]);
else add(a[pos],-a[pos]);
}
int main()
{
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
read(n); read(m); read(mod);
a[]=; dfs(,n,);
for(int i=;i<=m;i++)
{
read(e[i].l),read(e[i].r),read(e[i].x),read(e[i].y);
if(e[i].x>n) e[i].x=n;
if(e[i].y>n) e[i].y=n;
e[i].id=i;
}
int siz=sqrt(n);
for(int i=;i<=n;i++) bl[i]=(i-)/siz+;
sort(e+,e+m+,cmp);
int L=,R=,l,r;
for(int i=;i<=m;i++)
{
l=e[i].l; r=e[i].r;
while(L<l) update(L++,);
while(L>l) update(--L,);
while(R<r) update(++R,);
while(R>r) update(R--,);
if(e[i].x>) ans[e[i].id]=query(e[i].y)-query(e[i].x-);
else ans[e[i].id]=query(e[i].y);
}
for(int i=;i<=m;i++) printf("%I64d\n",ans[i]%mod);
}
树形DP+倍增
回想倍增法求LCA的过程
从大到小枚举k,每次跳2^k步,只要不越界就跳,最后一定能跳到LCA
因为跳的都是2的幂次步,所以每跳一步就是二进制加了一个1
先预处理fa[i][k],表示点i向上跳2^k 步的祖先节点
设 f[i][j] 表示最后一步跳了2^j步,跳到了点i的答案之和
cnt[i][j] 表示最后一步跳了2^j步,跳到了点i的方案数
因为有了倍增求lCA原理的保证,所以只需要考虑跳2的幂次步
设siz[i]表示以i为根的子树的大小
rt[i]=j 表示 当前点属于 i的子树里,以j为根节点的子树
假设dfs回溯到x,转移分两种:
1、以x为链的一个端点
枚举x向上跳2^k次,则v=fa[x][j]
那么ans+=siz[v]-siz[rt[v]] ——所有非rt[v]子树的点,与x的LCA都是v,都会有1的贡献
(类似于点分治中要去除同一子树内合法的点)
cnt[v][k]++ f[v][k]++
2、x作为倍增过程中的一个中途点
那么枚举最后一步跳了2^i 跳到了x
枚举x再往上跳2^j步,则v=fa[x][j]
那么ans+=(f[x][i]+cnt[x][i])*(siz[v]-siz[rt[v]])
f[x][i] 是原来的答案,在以v做LCA时,又会用 (siz[v]-siz[rt[v]])次
cnt[x][i] 是 要再往上跳2^j步,又有一个1的贡献
cnt[v][j]+=cnt[x][i] f[v][j]+=f[x][i]+cnt[x][i]
例:1--2--3--4 如果4到1的距离为3,二进制为11,对答案的贡献为2
回溯到4的时候,以4为端点会累积3--4 2--4
回溯到3的时候,以3为端点会累积2--3 1--3
回溯到2的时候,以2为端点会累积1--2,以2为中途点会累积1--2--3--4
(4跳2^1累积到2里,然后在枚举2为中途点时,最后一步跳了2^1到2,2再往上跳2^0)
为什么在枚举3作为中途点的时候,不枚举跳了2^0次方到了3
因为此时3不是中途点,我们是按跳2^k,k是降序跳的
个人总结:支持本题不重不漏的原理就是倍增求LCA的原理
或者是说任意数可以拆为2^k1+2^k2+2^k3…… ki 依次递减
个人AC代码
#include<cstdio>
#define N 100001 using namespace std; typedef long long LL; LL ans; int front[N],nxt[N<<],to[N<<],tot;
int fa[N][],siz[N],rt[N];
int cnt[N][],f[N][]; void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
} void dfs1(int x,int y)
{
fa[x][]=y; siz[x]=;
for(int i=;i<=;i++) fa[x][i]=fa[fa[x][i-]][i-];
for(int i=front[x];i;i=nxt[i])
if(to[i]!=y) dfs1(to[i],x),siz[x]+=siz[to[i]];
} void dfs2(int x)
{
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa[x][]) rt[x]=to[i],dfs2(to[i]);
for(int i=;i<=;i++)
{
ans+=siz[fa[x][i]]-siz[rt[fa[x][i]]];
cnt[fa[x][i]][i]++;
f[fa[x][i]][i]++;
}
for(int i=;i<=;i++)
for(int j=;j<i;j++)
{
ans+=LL(cnt[x][i]+f[x][i])*LL(siz[fa[x][j]]-siz[rt[fa[x][j]]]);
cnt[fa[x][j]][j]+=cnt[x][i];
f[fa[x][j]][j]+=f[x][i]+cnt[x][i];
}
} int main()
{
freopen("bitcount.in","r",stdin);
freopen("bitcount.out","w",stdout);
int n;
scanf("%d",&n);
int u,v;
for(int i=;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
}
dfs1(,);
siz[]=siz[]; nxt[]=;
dfs2();
printf("%I64d",ans);
}
自己加了中间输出辅助理解的std
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <vector> #define st first
#define nd second
using namespace std; struct edge {
int x;
int nxt;
};
typedef long long LL; const int N = 1E5 + ;
edge e[ * N];
int lca[N][], hd[N], fa[N], sons[N], nxt[N], cnt[N][], f[N][];
int n, m, x, y, l;
LL ans; void link(int x, int y) {
e[++l].x = y;
e[l].nxt = hd[x];
hd[x] = l;
} void dfs_lca(int x) {
lca[x][] = fa[x];
sons[x] = ;
for (int i = ; i <= ; ++i)
lca[x][i] = lca[lca[x][i - ]][i - ];
for (int p = hd[x]; p; p = e[p].nxt)
if (e[p].x != fa[x]) {
fa[e[p].x] = x;
dfs_lca(e[p].x);
sons[x] += sons[e[p].x];
}
} void dfs_ans(int x) {
for (int p = hd[x]; p; p = e[p].nxt)
if (e[p].x != fa[x]) nxt[x] = e[p].x, dfs_ans(e[p].x);
for (int i = ; i <= ; ++i) {
ans += sons[lca[x][i]] - sons[nxt[lca[x][i]]];
if(sons[lca[x][i]] - sons[nxt[lca[x][i]]]) printf("%d : sons[%d]-sons[%d]=%d\n",x,lca[x][i],nxt[lca[x][i]],sons[lca[x][i]] - sons[nxt[lca[x][i]]]);
cnt[lca[x][i]][i]++;
f[lca[x][i]][i]++;
}
for (int i = ; i <= ; ++i)
for (int j = ; j <= i - ; ++j) {
ans += LL(cnt[x][i] + f[x][i]) * LL(sons[lca[x][j]] - sons[nxt[lca[x][j]]]);
if(LL(cnt[x][i] + f[x][i]) * LL(sons[lca[x][j]] - sons[nxt[lca[x][j]]]))
printf("%d : cnt[%d][%d]+f[%d][%d] * sons[%d]-sons[%d] = %I64d\n",x,x,i,x,i,lca[x][j],nxt[lca[x][j]],LL(cnt[x][i] + f[x][i]) * LL(sons[lca[x][j]] - sons[nxt[lca[x][j]]]));
cnt[lca[x][j]][j] += cnt[x][i];
f[lca[x][j]][j] += f[x][i] + cnt[x][i];
}
} int main() {
//freopen("bitcount.in", "r", stdin);
//freopen("bitcount.out", "w", stdout);
scanf("%d", &n);
for (int i = ; i < n; ++i) {
scanf("%d%d", &x, &y);
link(x, y);
link(y, x);
}
dfs_lca();
sons[] = sons[];
nxt[] = ;
dfs_ans();
printf("%I64d\n", ans);
}
考场60分暴力
#include<cstdio>
#include<algorithm>
#define N 2001
using namespace std;
int front[N],to[N<<],nxt[N<<],tot;
int val[N],deep[N],id[N];
int lca[N][N],f[N][];
int n;
void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
}
int cal(int x)
{
int sum=;
while(x) sum+=(x&),x>>=;
return sum;
}
void dfs(int x,int dep,int fa)
{
id[x]=++tot; deep[x]=dep;
f[x][]=fa;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa) dfs(to[i],dep+,x);
}
int getlca(int x,int y)
{
if(id[x]<id[y]) swap(x,y);
for(int i=;i>=;i--)
if(id[f[x][i]]>id[y]) x=f[x][i];
return f[x][];
}
void prelca()
{
for(int j=;j<=;j++)
for(int i=;i<=n;i++)
f[i][j]=f[f[i][j-]][j-];
for(int i=;i<n;i++)
for(int j=i+;j<=n;j++)
lca[i][j]=getlca(i,j);
}
void solve()
{
int ans=;
for(int i=;i<n;i++)
for(int j=i+;j<=n;j++)
ans+=val[deep[i]-deep[lca[i][j]]]+val[deep[j]-deep[lca[i][j]]];
printf("%d",ans);
}
int main()
{
freopen("bitcount.in","r",stdin);
freopen("bitcount.out","w",stdout);
scanf("%d",&n);
int u,v;
for(int i=;i<n;i++) { scanf("%d%d",&u,&v); add(u,v); }
for(int i=;i<=n;i++) val[i]=cal(i);
tot=; dfs(,,);
prelca();
solve();
}
2017北京国庆刷题Day5 morning的更多相关文章
- 2017北京国庆刷题Day5 afternoon
期望得分:100+60+100=260 实际得分:0+60+40=100 设图中有m个环,每个环有si条边,有k条边不在环中 ans= (2^s1 -2)*( 2^s2 -2)* (2^s3 -2)… ...
- 2017北京国庆刷题Day1 afternoon
期望得分:100+100+100=300 实际得分:100+100+100=300 T1 一道图论好题(graph) Time Limit:1000ms Memory Limit:128MB 题目 ...
- 2017北京国庆刷题Day7 morning
期望得分:100+0+100=200 实际得分:100+20+0=120 离散化搞搞 #include<cstdio> #include<iostream> #include& ...
- 2017北京国庆刷题Day3 morning
期望得分:100+60+0=160 实际得分:100+30+0=130 考场上用的哈希 #include<cstdio> #include<cstring> #include& ...
- 2017北京国庆刷题Day2 afternoon
期望得分:100+100+50=250 实际得分:100+70+50=220 T1 最大值(max) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一 ...
- 2017北京国庆刷题Day2 morning
期望得分:100+100+40=240 实际得分:100+40+0=140 T1 一道图论神题(god) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK ...
- 2017北京国庆刷题Day4 morning
期望得分:0+40+30=70 实际得分:0+10+10=20 题目修改:只能由0变1,只能用一次操作 大模拟 #include<cstdio> #include<cstring&g ...
- 2017北京国庆刷题Day4 afternoon
期望得分:100+100+0=200 实际得分:5+0+0=5 每加入一个数,x的因数位置++ 注意:根号x枚举时,如果x是完全平方数,根号x会重复累计2次,要减去 考场上没减,5分 /(ㄒoㄒ)/~ ...
- 2017北京国庆刷题Day6 afternoon
期望得分:100+100+40=240 实际得分:100+0+40=140 二进制拆分.二进制前缀和 #include<cstdio> #include<iostream> u ...
随机推荐
- ZOJ 3946 Highway Project 贪心+最短路
题目链接: http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3946 题解: 用dijkstra跑单元最短路径,如果对于顶点v,存 ...
- C++ Primer Plus学习:第五章
C++入门第五章:循环和关系表达式 for循环 for循环的组成部分 设置初始值. 执行测试,看循环是否应该继续执行. 执行循环操作. 更新用于测试的值. 以上操作由括号括起,每个部分均是一个表达式, ...
- Struts2(三)
以下内容是基于导入struts2-2.3.32.jar包来讲的 1.全局视图配置 xml标签:<global-results> <result name="error&qu ...
- jetty之maven配置
<!-- jetty 插件配置 --><plugin> <groupId>org.mortbay.jetty</groupId> <artifac ...
- (转)设置Sysctl.conf用以提高Linux的性能(最完整的sysctl.conf优化方案)
Sysctl是一个允许您改变正在运行中的Linux系统的接口.它包含一些 TCP/IP 堆栈和虚拟内存系统的高级选项, 这可以让有经验的管理员提高引人注目的系统性能.用sysctl可以读取设置超过五百 ...
- 超强汇总!110 道 Python 面试笔试题
https://mp.weixin.qq.com/s/hDQrimihoaHSbrtjLybZLA 今天给大家分享了110道面试题,其中大部分是巩固基本python知识点,希望刚刚入手python,对 ...
- IIS部署时failed to execute url 解决方法
web.config中增加如下节点: <system.webServer> <validation validateIntegratedModeConfiguration=&quo ...
- 在64位系统上部署BDE的要点
首先,据我所知,Borland/CodeGear没有发布过支持64bit windows的BDE安装包,如果你在网上看到了相关的BDE安装包,很有可能是使用者自己重新打包发布的. 无论是在32bit ...
- Ubuntu 18.04开发环境部署流程
部署流程 安装系统 安装Eclipse和jre 配置系统 安装辅助工具 安装系统 用安装盘安装即可. 一般boot 1G,swap按内存大小,home 20G,根剩余. 安装Eclipse和jre 解 ...
- 【HLSDK系列】怎么增加一种新实体
你平常肯定接触到很多比如 info_player_start hostage info_target 之类的实体,这里就解释一下怎么创建一种新的实体. 首先建立一个新的 .h 文件(当然你写在现有的文 ...