期望得分: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=0;for (int i=1;i<=n;++i) {scanf("%d",&y);x=gcd(x,abs(y));}if (n==1) 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");
}

View Code

每次分两半的时候,一定是奇数在左边,偶数在右边

所以用类似于线段树的思想来分治

由于每次讲将序列按奇偶下标分成两半,如果每次处理分成的那一半区间

那这个区间一定是一个等差数列,且公差为 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=0; char c=getchar();while(!isdigit(c)) c=getchar();while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}pr solve(LL rr,LL l,LL r,LL x,LL y)
{if(x>rr || l>r) return mp(0,0);if(l==1 && r==rr){y=min(y,rr);LL s;if (!((x+y)&1))s=(x+y>>1)%mod*((y-x+1)%mod)%mod;else s=((x+y)%mod)*((y-x+1>>1)%mod)%mod;return mp(s,(y-x+1)%mod);}LL mid=rr+1>>1;if(r<=mid) {pr res=solve(mid,l,r,(x>>1)+1,y+1>>1);return mp(((res.first<<1)-res.second)%mod,res.second);}if(l>mid){pr res=solve(rr-mid,l-mid,r-mid,x+1>>1,y>>1);return mp((res.first<<1)%mod,res.second);}pr res1=solve(mid,l,mid,(x>>1)+1,y+1>>1);pr res2=solve(rr-mid,1,r-mid,x+1>>1,y>>1);return mp(((res1.first<<1)-res1.second+(res2.first<<1))%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);}
}

View Code

考场 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=0; char c=getchar();while(!isdigit(c)) c=getchar();while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}
void dfs(int l,int r,int k)
{if(l==r) return;int m=l+r>>1,t=m;dfs(l,m,k<<1);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=0;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[1]=1; dfs(1,n,1);for(int i=1;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=1;i<=n;i++) bl[i]=(i-1)/siz+1;sort(e+1,e+m+1,cmp);int L=1,R=0,l,r;for(int i=1;i<=m;i++){l=e[i].l; r=e[i].r;while(L<l) update(L++,0);while(L>l) update(--L,1);while(R<r) update(++R,1);while(R>r) update(R--,0);if(e[i].x>1) ans[e[i].id]=query(e[i].y)-query(e[i].x-1);else ans[e[i].id]=query(e[i].y);}for(int i=1;i<=m;i++) printf("%I64d\n",ans[i]%mod);
}

View Code

树形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 100001using namespace std;typedef long long LL;LL ans;int front[N],nxt[N<<1],to[N<<1],tot;
int fa[N][17],siz[N],rt[N];
int cnt[N][17],f[N][17];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][0]=y; siz[x]=1;for(int i=1;i<=16;i++) fa[x][i]=fa[fa[x][i-1]][i-1];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][0]) rt[x]=to[i],dfs2(to[i]);for(int i=0;i<=16;i++){ans+=siz[fa[x][i]]-siz[rt[fa[x][i]]];cnt[fa[x][i]][i]++;f[fa[x][i]][i]++;}for(int i=1;i<=16;i++)for(int j=0;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=1;i<n;i++){scanf("%d%d",&u,&v);add(u,v);}dfs1(1,0);siz[0]=siz[1]; nxt[0]=1;dfs2(1);printf("%I64d",ans);
}

View Code

自己加了中间输出辅助理解的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 + 10;
edge e[2 * N];
int lca[N][17], hd[N], fa[N], sons[N], nxt[N], cnt[N][17], f[N][17];
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][0] = fa[x];sons[x] = 1;for (int i = 1; i <= 16; ++i)lca[x][i] = lca[lca[x][i - 1]][i - 1];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 = 0; i <= 16; ++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 = 1; i <= 16; ++i)for (int j = 0; j <= i - 1; ++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 = 1; i < n; ++i) {scanf("%d%d", &x, &y);link(x, y);link(y, x);}dfs_lca(1);sons[0] = sons[1];nxt[0] = 1;dfs_ans(1);printf("%I64d\n", ans);
}

View Code

考场60分暴力

#include<cstdio>
#include<algorithm>
#define N 2001
using namespace std;
int front[N],to[N<<1],nxt[N<<1],tot;
int val[N],deep[N],id[N];
int lca[N][N],f[N][12];
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=0;while(x) sum+=(x&1),x>>=1;return sum;
}
void dfs(int x,int dep,int fa)
{id[x]=++tot; deep[x]=dep;f[x][0]=fa;for(int i=front[x];i;i=nxt[i])if(to[i]!=fa) dfs(to[i],dep+1,x);
}
int getlca(int x,int y)
{if(id[x]<id[y]) swap(x,y);for(int i=11;i>=0;i--)if(id[f[x][i]]>id[y]) x=f[x][i];return f[x][0];
}
void prelca()
{for(int j=1;j<=11;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];for(int i=1;i<n;i++)for(int j=i+1;j<=n;j++)lca[i][j]=getlca(i,j);
}
void solve()
{int ans=0;for(int i=1;i<n;i++)for(int j=i+1;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=1;i<n;i++)  {  scanf("%d%d",&u,&v); add(u,v); }for(int i=1;i<=n;i++) val[i]=cal(i);tot=0; dfs(1,0,0);prelca();solve();
}

View Code

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/7655156.html

2017北京国庆刷题Day5 morning相关推荐

  1. 2017北京国庆刷题Day5 afternoon

    期望得分:100+60+100=260 实际得分:0+60+40=100 设图中有m个环,每个环有si条边,有k条边不在环中 ans= (2^s1 -2)*( 2^s2 -2)* (2^s3 -2)- ...

  2. 2017北京国庆刷题Day2 afternoon

    期望得分:100+100+50=250 实际得分:100+70+50=220 T1 最大值(max) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一 ...

  3. LeetCode779 第K个语法符号 python刷题Day5

    779.第K个语法符号 差一点今天就前功尽弃了,瘫在沙发上一时爽,一直瘫着废到老.想想昨天被一道评级为简单的题困住了.虽然我上学上的久,但我学的东西少啊.好了,开正题了,士可以一日不食而不能半日不学. ...

  4. 【套题】qbxt国庆刷题班D1

    Day1 事实上D1的题目还是比较简单的= =然而D1T2爆炸了就十分尴尬--错失一波键盘 看题 T1 传送门 Description 现在你手里有一个计算器,上面显示了一个数\(S\),这个计算器十 ...

  5. 对于清北学堂2018国庆刷题班的学习总结

    \(10.1\) 例题1: 最多因子数(Link) 给定一个区间\([L, R]\),要求求出在区间内拥有最大因子数的数. 定义\(F(X)\)为\(X\)的因子个数函数.首先我们要知道,对于任意一个 ...

  6. 2017 北京赛区 J题 Pangu and Stones 【区间DP】

    题目链接:https://vjudge.net/problem/HihoCoder-1636: 题意:n堆石子,每次可以合并连续的 [ L~R ]堆石子,求最少的代价: /* 思路:区间DP;dp[i ...

  7. 国庆作业 刷题0929

    国庆作业 刷题0929 使进度在90-95%截图上传 详情 第二本书 第一本书

  8. 【代码随想录】刷题笔记Day5

    前言 竟然足足一星期没刷题了,上周毕设紧急赶了波工,就没什么动力,希望不会因此生疏了,组会过后刷新了焦虑值,又是新的一周,干巴爹 209. 长度最小的子数组 暴力解法:时间复杂度O(n2),两个for ...

  9. 2017.5.27测试 2. 刷题(P1167)

    2 刷题 (c.pas/cpp/c) [题目背景] "好啊!一言为定!!",作为蒟蒻的GJY竟然约定和神犇来一场世纪大战. [题目描述] GJY在期末的时候跟神犇约定了一次战争,这 ...

最新文章

  1. 麻省理工学院揭秘男女配对的真相
  2. 2018年Github最受欢迎机器学习语言Python稳坐冠军,numpy、scipy是最受欢迎软件包...
  3. Zend Framework 的 PHP 编码标准
  4. 简述http请求中的同步和异步
  5. wxWidgets:wxCollapsiblePane类用法
  6. Python数据分析入门(四)
  7. c++:怎么将ctime时间转化为一个具体的秒数值_Linux下如何删除长时间不使用的旧文件?...
  8. android单个页面切换_Android基础之使用Fragment控制切换多个页面
  9. BurpSuite之HTTP brute暴力破解
  10. 练习题︱基于今日头条开源数据(二)——两款Apriori算法实践
  11. 如何用纯 CSS 创作 404 文字变形为 NON 文字的交互特效
  12. java读取zip文件损坏_java zip压缩文件损坏
  13. 51单片机流水灯现象2
  14. Linux中巧用zip命令压缩和解压缩文件
  15. 【读后感1】读《我是一只it小小鸟》有感
  16. canvas 文字颜色_Canvas 超全教程
  17. App Store拒绝原因
  18. Socket网络编程详解
  19. 56 行代码,带你爬取豆瓣影评
  20. 上海居住证及居住证积分常见问题(70个常见问题)

热门文章

  1. Python入门--字符串的分割操作,split,rsplit
  2. 二分--求最小值的最大p1m2
  3. C++优先队列自定义排序总结
  4. mooc中的习题--然后是几点
  5. Binary tree paths-深度优先遍历DFS
  6. hls和modelsim联合仿真生成波形找不到wlf文件
  7. quartus仿真29:JK触发器实现序列信号发生器0010111(分析)
  8. 2步判断晶体管工作状态
  9. 十八.搭建Nginx服务器、配置网页认证、基于域名的虚拟主机、ssl虚拟主机
  10. vim学习 07——跳转缩进