1. 公约数(gcd)

  1. 【问题描述】
  2. 给定一个正整数,在[,n]的范围内,求出有多少个无序数对(a,b)满足
  3. gcd(a,b)=a xor b
  4. 【输入格式】
  5. 输入共一行,一个正整数n
  6. 【输出格式】
  7. 输出共一行,一个正整数表示答案。
  8. 【输入输出样例】
  9. gcd .in gcd .out
  10.  
  11. 解释:只有(,)满足要求
  12. 【数据范围】
  13. 对于30%的数据满足n<=
  14. 对于60%的数据满足n<=^
  15. 对于100%的数据满足n<=^

题目

tag:数学

思路:就一个等式,gcd(a,b)==d==a^b,我们要把它扩展开来,由于a==b无解,设a严格大于b,d|a,d|b==〉d|(a-b),则a-b>=d=gcd(a,b)。a^b显然>=a-b,因为每一位异或的结果要么比减法大要么跟减法一样。最后得gcd(a,b)<=a-b<=a^b。现在看需要枚举啥子,取特 gcd(a,b)=a-b=a^b=d,运用异或的性质得a^d=b代回去,a-a^d=d,移项a-d=a^d,枚举d和d的倍数即可。这个算法的时间复杂度是O(nlogn)。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. using namespace std;
  6. int n,ans;
  7. int main()
  8. {
  9. //freopen("gcd.in","r",stdin);
  10. //freopen("gcd.out","w",stdout);
  11. scanf("%d",&n);
  12. for(int i=;i<=n;++i)
  13. for(int j=n/i;j>=;--j){
  14. int a=i*j;
  15. if((a-i)==(a^i)) ans++;
  16. }
  17. printf("%d",ans);
  18. return ;
  19. }

2. 通讯(message)

  1. 【问题描述】“这一切都是命运石之门的
  2. 选择。”
  3. 试图研制时间机器的机关 SERN 截获了中二科学家伦太郎发往过去的一条
  4. 短信,并由此得知了伦太郎制作出了电话微波炉(仮)。
  5. 为了掌握时间机器的技术,SERN 总部必须尽快将这个消息通过地下秘密通讯
  6. 网络,传达到所有分部。
  7. SERN 共有 N 个部门(总部编号为 ),通讯网络有 M 条单向通讯线路,每条
  8. 线路有一个固定的通讯花费 Ci
  9. 为了保密,消息的传递只能按照固定的方式进行:从一个已知消息的部门向
  10. 另一个与它有线路的部门传递( 可能存在多条通信线路)。我们定义总费用为所
  11. 有部门传递消息的费用和。
  12. 幸运的是,如果两个部门可以 直接或间接地相互传递消息(即能按照上述方法
  13. 将信息由 X 传递到 Y,同时能由 Y 传递到 X),我们就可以忽略它们之间的花费。
  14. 由于资金问题(预算都花在粒子对撞机上了),SERN 总部的工程师希望知道,
  15. 达到目标的最小花费是多少。
  16. 【输入格式】多组数据,文件以
  17. 结尾。
  18. 每组数据第一行,一个整数 N,表示有 N 个包括总部的部门(从 开始编号)。
  19. 然后是一个整数 M,表示有 M 条单向通讯线路。
  20. 接下来 M 行,每行三个整数,Xi,Yi,Ci,表示第 i 条线路从 Xi 连向 Yi,花费

  21. Ci
  22. 【输出格式】
  23. 每组数据一行,一个整数表示达到目标的最小花费。
  24. 【输入输出样例】
  25. message.in
  26.  
  27. message.out
  28.  
  29. 【样例解释】第一组数据:总部把消息传给分部 ,分部 再传给分
  30. .总费用:
  31. +=.
  32. 第二组数据:总部把消息传给分部 ,由于分部 和分部 可以互相传递消
  33. 息,所以分部 可以无费用把消息传给 .总费用:+=.
  34. 第三组数据:总部把消息传给分部 ,最小费用为 .总费用:.
  35. 【数据范围】对于 %的数据,
  36. 保证 M=N-
  37. 对于另 %的数据,N M 对于 %的数据,N
  38. M ^ Ci ^ ,数据组数
  39. 数据保证一定可以将信息传递到所有部门。

题目

tag:强连通分量,缩点,贪心

思路:tarjan求强连通分量,缩点后形成DAG的树状结构。乍一看是最小生成树,根据题意,除起点的每个点都有可以到它的边,既然最后都能到达,选最小的那个边就行了。如果用最小生成树,起点可能会“被”连接,用贪心法一开始把minv[st]置0可以避免这种情况。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cmath>
  5. #include<stack>
  6. #define maxn 100010
  7. using namespace std;
  8. int cnt,tot,ans,n,m,num,dfn[maxn],low[maxn],vis1[maxn],vis2[maxn],hl[maxn],HL[maxn],jh[maxn],own[maxn],fa[maxn],minv[maxn];
  9. stack<int>S;
  10. struct Edge{
  11. int u,v,w,ne;
  12. }e[maxn<<],E[maxn<<];
  13. void init()
  14. {
  15. cnt=tot=ans=num=;
  16. memset(dfn,,sizeof(dfn));
  17. memset(low,,sizeof(low));
  18. memset(vis1,,sizeof(vis1));
  19. memset(vis2,,sizeof(vis2));
  20. memset(hl,,sizeof(hl));
  21. memset(HL,,sizeof(HL));
  22. memset(e,,sizeof(e));
  23. memset(E,,sizeof(E));
  24. memset(jh,,sizeof(jh));
  25. memset(own,,sizeof(own));
  26. memset(fa,,sizeof(fa));
  27. memset(minv,/,sizeof(minv));
  28. }
  29. void add(int u,int v,int w)
  30. {
  31. e[++cnt].u=u;
  32. e[cnt].v=v;
  33. e[cnt].w=w;
  34. e[cnt].ne=hl[u];
  35. hl[u]=cnt;
  36. }
  37. int find(int x)
  38. {
  39. return x==fa[x]?x:fa[x]=find(fa[x]);
  40. }
  41. void tarjan(int x)
  42. {
  43. S.push(x);
  44. dfn[x]=low[x]=++tot;
  45. vis1[x]=vis2[x]=;
  46. for(int i=hl[x];i;i=e[i].ne){
  47. int v=e[i].v;
  48. if(!vis1[v]){
  49. tarjan(v);
  50. low[x]=min(low[x],low[v]);
  51. }
  52. else if(vis2[v]) low[x]=min(low[x],dfn[v]);
  53. }
  54. if(dfn[x]==low[x]){
  55. num++;
  56. int now=-;
  57. while(now!=x){
  58. now=S.top();
  59. S.pop();
  60. jh[now]=num;
  61. own[num]++;
  62. vis2[now]=;
  63. }
  64. }
  65. }
  66. void rebuild()
  67. {
  68. for(int i=;i<n;++i)
  69. for(int j=hl[i];j;j=e[j].ne){
  70. int v=e[j].v;
  71. if(jh[i]!=jh[v]){
  72. E[++cnt].u=jh[i];
  73. E[cnt].v=jh[v];
  74. E[cnt].w=e[j].w;
  75. E[cnt].ne=HL[jh[i]];
  76. HL[jh[i]]=cnt;
  77. }
  78. }
  79. }
  80. bool cmp(Edge x,Edge y)
  81. {
  82. return x.w<y.w;
  83. }
  84. int main()
  85. {
  86. //freopen("message.in","r",stdin);
  87. //freopen("message.out","w",stdout);
  88. int x,y,w;
  89. while(scanf("%d%d",&n,&m)!=EOF){
  90. init();
  91. if(!n&&!m) break;
  92. for(int i=;i<=m;++i){
  93. scanf("%d%d%d",&x,&y,&w);
  94. add(x,y,w);
  95. }
  96. for(int i=;i<n;++i) if(!vis1[i]) tarjan(i);
  97. cnt=tot=;
  98. rebuild();
  99. minv[jh[]]=;
  100. for(int i=;i<=num;++i)
  101. for(int j=HL[i];j;j=E[j].ne){
  102. int v=E[j].v;
  103. minv[v]=min(E[j].w,minv[v]);
  104. }
  105. for(int i=;i<=num;++i) ans+=minv[i];
  106. printf("%d\n",ans);
  107. }
  108. return ;
  109. }

3.label(label)

  1. 【问题描述】
  2. SamjiaPeter不同,他喜欢玩树。所以Peter送给他一颗大小为n的树,节
  3. 点编号从1n
  4. Samjia要给树上的每一个节点赋一个[,m]之间的权值,并使得有边直接相
  5. 连的两个节点的权值之差的绝对值 k。请你告诉Samjia有多少种不同的赋值
  6. 方案,只用求出答案对10
  7. +()取模得到的结果。
  8. 【输入格式】
  9. 输入文件名为 label.in
  10. 输入数据的第一行包含一个整数 T,代表测试数据组数。
  11. 接下来是 T 组数据.
  12. 每组数据的第一行包含三个整数 nm k
  13. 接下来 n 行,每行包含两个整数 u v 代表节点 u v 之间有
  14. 一条树边。
  15. 【输出格式】
  16. 输出文件名为 label.out
  17. 对于每组数据,输出一行,包含一个整数,代表所求的答案。
  18. 【输入输出样例】
  19. label.in label.out
  20.  
  21. 【输入输出样例说明】
  22. 对于第一组样例,满足的方案如图
  23. 图中方括号内的数字([x])代表给节点赋的值。
  24. 【数据规模与约定】
  25. 测试点编号 m 特殊约定
  26. ,
  27. ,
  28. , ^ 2-n号节点与1号节点直接相连
  29. , ^ i号节点与第i+1号节点直接相连
  30. , ^
  31. 对于所有数据,T≤,n≤,k≤,m≤^

题目

tag:树形DP

思路:对于这道树形DP来说,父节点的取值决定了子节点的取值范围,子节点的方案数通过使用加法原理和乘法原理继承给父节点。但暴力枚举只能拿到20分。我们运用数学归纳,发现对于每个节点X,满足f[x][i]=f[x][m-i+1],也就是说它的取值是对称的。其实,如果可取的长度相等,DP(f)的值也相等。再考虑,如果当m特别大而k很小,就有很长一段区间内每个点的DP值都相等,如下图。

如果这两个区间同时向外移动,因为对称性,他们的值同步变化。那么,我们有必要把100 * 10^9 个值都存到数组里吗?答案当然是,没有。最多只会有(maxn-1)*maxk个不同的值,也就是说,我们只用保存最多9900(limit)个数,当调用时直接去找每个值存他的地方,把大区间分左(1~limit)、中(limit~m-limit)、右(m-limit~m),在左区间直接调用,让limit储存中区间的所有点的那个相同值,在右区间,找左区间的对称点。

解决了空间问题,还有更麻烦的时间问题,我们每取一个值,都会生成完全不同的范围,如果每次都进行计算是不是太过麻烦?不过,很容易发现,从1取到limit,它们生成的区间有一定变化规律,大部分是不会变的,左右两端进行微调,右端退出,左端进入(详见注释)。

我们还需要求出当取值为1时的初始区间,之后才能在上面进行修改。getsum——左中右的处理方式各异,左右每个点值都不同,需要暴力枚举,中区间只求有多少个点再乘值。

还有个小技巧,k=0的时候直接快速幂m^n输出。最后的答案就是根节点所有DP值的和,我们用现成的getsum可以直接求。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cmath>
  5. #include<stack>
  6. #define maxn 10010
  7. #define ll long long
  8. using namespace std;
  9. const int mod = 1e9 + ;
  10. int ans,k,hl[maxn],fa[maxn],cnt,n,m,T,lim,f[][maxn];
  11. struct Edge{
  12. int u,v,w,ne;
  13. }e[maxn<<];
  14. void init()
  15. {
  16. memset(hl,,sizeof(hl));
  17. memset(fa,,sizeof(fa));
  18. memset(f,,sizeof(f));
  19. memset(e,,sizeof(e));
  20. cnt=ans=;
  21. }
  22. void add(int u,int v)
  23. {
  24. e[++cnt].u=u;
  25. e[cnt].v=v;
  26. e[cnt].ne=hl[u];
  27. hl[u]=cnt;
  28. }
  29. ll getsum(int x,int st)
  30. {
  31. ll ret=;
  32. for(int i=st;i<=lim;++i) ret=(ret+f[x][i])%mod;//起点在左区间 计算从起点到lim
  33. for(int i=m;i>m-lim&&i>lim&&i>=st;--i) ret=(ret+f[x][m-i+])%mod;//类似上一行 计算右区间
  34. int l=max(st,lim+),r=m-lim;//计算中区间范围
  35. int len=r-l+;
  36. if(len>) ret=(ret+1ll*len*f[x][lim]%mod)%mod;
  37. return ret;
  38. }
  39. void dfs(int x)
  40. {
  41. for(int i=hl[x];i;i=e[i].ne){
  42. int v=e[i].v;
  43. if(v==fa[x]) continue;
  44. fa[v]=x;
  45. dfs(v);
  46. }
  47. for(int i=;i<=lim;++i) f[x][i]=;
  48. for(int i=hl[x];i;i=e[i].ne){
  49. int v=e[i].v;
  50. if(v==fa[x]) continue;
  51. ll sum=getsum(v,k+);//初始值
  52. for(int j=;j<=lim;++j){
  53. if(j-k>=) sum=(sum+f[v][j-k])%mod;//左端点增加区间
  54. f[x][j]=1ll*f[x][j]*sum%mod;//乘法原理
  55. int bj=j+k;//右端点
  56. if(bj<=m){//右端点还在大范围内
  57. if(m-bj+<=lim) bj=m-bj+;//将右区间定位到左区间
  58. else if(bj>=lim) bj=lim;//中区间定位到lim点
  59. sum=((sum-f[v][bj])%mod+mod)%mod;//右端点退出区间
  60. }
  61. }
  62. }
  63. }
  64. int ksm(int a,int B)
  65. {
  66. int x=a,b=B,ret=;
  67. while(b){
  68. if(b&) ret= 1ll*ret*x %mod;
  69. x= 1ll*x*x%mod;
  70. b>>=;
  71. }
  72. return ret;
  73. }
  74. int main()
  75. {
  76. //freopen("label.in","r",stdin);
  77. //freopen("label.out","w",stdout);
  78. int x,y;
  79. scanf("%d",&T);
  80. while(T--){
  81. init();
  82. scanf("%d%d%d",&n,&m,&k);
  83. for(int i=;i<n;++i){
  84. scanf("%d%d",&x,&y);
  85. add(x,y);
  86. add(y,x);
  87. }
  88. if(!k){
  89. printf("%d\n",ksm(m,n));
  90. continue;
  91. }
  92. lim=min(,m);
  93. dfs();
  94. printf("%d\n",getsum(,));
  95. }
  96. return ;
  97. }

↑系统自带分割线

芒果君:这次大——————翻车!!!然后订正+解题报告又弄了好久QAQ 无fa可说OTZ

冲刺Noip2017模拟赛5 解题报告——五十岚芒果酱的更多相关文章

  1. 冲刺Noip2017模拟赛2 解题报告——五十岚芒果酱

    题1 牛跑步(running) [题目描述] 新牛到部队,CG 要求它们每天早上搞晨跑,从 A 农场跑到 B 农场.从 A 农场到 B 农场中有 n- 个路口,分别标上号,A 农场为 号,B 农场为 ...

  2. 冲刺Noip2017模拟赛1 解题报告——五十岚芒果酱

    题1 国际象棋(chess) [问题描述] 有N个人要参加国际象棋比赛,该比赛要进行K场对弈.每个人最多参加2场对弈,最少参加0场对弈.每个人都有一个与其他人都不相同的等级(用一个正整数来表示).在对 ...

  3. 冲刺Noip2017模拟赛3 解题报告——五十岚芒果酱

    题1  素数 [问题描述] 给定一个正整数N,询问1到N中有多少个素数. [输入格式]primenum.in 一个正整数N. [输出格式]primenum.out 一个数Ans,表示1到N中有多少个素 ...

  4. 冲刺Noip2017模拟赛8 解题报告——五十岚芒果酱

    1.鼎纹 [问题描述] 据说鼎纹的 种制造 式是 铜模印出来的,这是我国古代劳动 智慧 的结晶.铜模印过的地 ,会留下深深的印记,经过时间的炼化,洗 练成历史的遗存. 聪明的古代劳动人民拥有一个 a ...

  5. 冲刺Noip2017模拟赛7 解题报告——五十岚芒果酱

    1.二叉树(binary) .二叉树 (binary.cpp/c/pas) [问题描述] 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: ()若左子树不空,则左子树上所有结点的值均小于它的根结 ...

  6. 冲刺Noip2017模拟赛6 解题报告——五十岚芒果酱

    1.ksum(ksum) [问题描述] Peter喜欢玩数组.NOIP这天,他从Jason手里得到了大小为n的一个正整数 数组. Peter求出了这个数组的所有子段和,并将这n(n+)/2个数降序排序 ...

  7. 冲刺Noip2017模拟赛4 解题报告——五十岚芒果酱

    题1 韬韬抢苹果(apple) [问题描述] 又到了收获的季节,树上结了许多韬韬,错了,是许多苹果,有很多个小韬韬都来摘苹 果.每个韬韬都想要最大的苹果,所以发生了争执,为了解决他们的矛盾,出题人定了 ...

  8. 20161005 NOIP 模拟赛 T2 解题报告

    beautiful 2.1 题目描述 一个长度为 n 的序列,对于每个位置 i 的数 ai 都有一个优美值,其定义是:找到序列中最 长的一段 [l, r],满足 l ≤ i ≤ r,且 [l, r] ...

  9. 【HHHOJ】NOIP模拟赛 玖 解题报告

    点此进入比赛 得分: \(100+20+100=220\)(还不错) 排名: \(Rank\ 16\) \(Rating\):\(+20\) \(T1\):[HHHOJ263]「NOIP模拟赛 玖」三 ...

随机推荐

  1. [Functional Programming] Using ComposeK for both get State and modify State

    We have State like this: const state = { cards: [ { id: "green-square", color: "green ...

  2. DbVisualizer 连接AS400

    1.安装DbVisualizer 2.下载JTopen 里面会有jt400.jar http://sourceforge.net/projects/jt400/files/latest/downloa ...

  3. 富文本编辑器粘贴word

    很多时候我们用一些管理系统的时候,发布新闻.公告等文字类信息时,希望能很快的将word里面的内容直接粘贴到富文本编辑器里面,然后发布出来.减少排版复杂的工作量. 下面是借用百度doc 来快速实现这个w ...

  4. while练习

    题目:企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%:利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%:20万到40万之 ...

  5. codeforces#1290E2 - Rotate Columns (hard version)(子集dp)

    题目链接: https://codeforces.com/contest/1209/problem/E2 题意: 给出$n$行和$m$列 每次操作循环挪动某列一次 可以执行无数次这样的操作 让每行最大 ...

  6. java web课程管理系统开发实例(从数据库连接到代码)

    以下是几个简单知识: JavaBean:用于传递数据,拥有与数据相关的逻辑处理 JSP:从Model接收数据并生成HTML Servlet:接收HTTP请求并控制Model和View jdbc:用于配 ...

  7. springboot的注解

    1.@ConfigurationProperties 功能:装载配置文件信息到实体 原理:aop,通知类型:?(方法或对象创建完后) 注意:作用于方法上可以不需要改源码(例如durid配置) 转载:h ...

  8. easyui复选框实现单选框

    $(':checkbox[name=primary_key_flag]').each(function(){ $(this).click(function(){ if(this.checked){ $ ...

  9. Logback 日志策略配置

    [参考文章]:官方文档:Logback configuration [参考文章]:logback的使用和logback.xml详解 [参考文章]:Logback源码赏析-日志按时间滚动(切割) 1. ...

  10. pod package 生成 Framework

    pod package 生成 Framework pod package 是 cocoapods 的一个插件,如果没有的话使用以下命令安装: sudo gem install cocoapods-pa ...