一套不错的题,需要相关资料的联系我咯

考试分析:

1.  由于题目的名字加上第一道题没读完时我以为是我最不擅长的treeDP(其实不得不说,树和图上的题我真的是不想写,一般都写不对,上课太不认真,这个弱点要加强训练),我直接跳到了最后一道题,明知考3h还用了30min去分析,不过还是感谢,这30min救了我两道题出来;

这套题的确还是比较简单,后两道题只要认真分析数据都不会有问题,也许是因为暑假切了贪心和递推,我对分析数据比较在行,第三题切完之后还有2h,不过没写高精的我有点慌,打算最后留一点时间来补,然后第一次写矩阵快速幂速度还不错,很快就搞定了,然而卡死在了快速幂上——对快速幂调试了30Min,没什么好怨天尤人的,至少这不是NOIP2016,知道了不会就好好补;然后最后终于过了,时间估算错误以为能过50分,结果log1e9可以看成比较大的常数,ll又慢,就只拿了30分;后来5分钟想了一下优化,没有静下来而且一昧否定,总觉得优化就不能快速幂了没注意自己可以改写法,也算是上了一课吧;

然后分给第一题的时间只有30min了,没有分析只想着能写多少是多少,然而感谢暑假训练来的代码实现能力,几乎10min一次过,不知道多一点时间我能不能分析出来,不过我也满意了,希望以后不要花那么多时间来调试以免耽误时间

回过头来给第三题完结了一下,不然的话和普通算法没有任何区别——嗯就是相等跳出那里;

2.第二题分析过程:

首先,这反常地是一道很容易看出递推的提题,然后我们要开始抽象化,撇开数值的关系后我们发现,这道题对于某个点来说,它自身数值的系数,周围不同距离的点的系数都是有关系的,于是决定直接算系数,这里就可以用到我刚刚学的矩阵快速幂;

矩阵快速幂的用处其实就是优化这种算很多次而系数又不好算的递推;但是,由于配数据的失误?只过了30分;

正解比矩阵快速幂还要高端一点,是我在考试时没捣鼓出来的序列乘法,利用的是这个矩阵的对称性,其实 递推中应该很多这种多项式本来系数就相同的多次递推,都可以用序列乘法优化到n^2;

3.  手算大法好;拿到以后,迫于题目名字的压力,不敢不全过,然而1e12肯定是不能白过的,于是开始手算找解法顺便放松心情(什么!),算了11 11没有规律,然后21 21开始发现规律了:怎么是等差呢?好奇怪;然后抱着半确定的心算了50 50,果然是这样,正确性也能得到证明,只是这道“最简单的题”算下来应该是要用高精度的,结果配数据的神牛也才发现这件事,默默地配成了ll,由于这套题只考3小时,分析了30min担心没时间的我没有写高精,居然歪打正着地A了,看到cena一片绿简直开心;

4.  手算大法好,还可以用来自己防止出错,对分析数据也很有利;

5.  学过的东西一定要好好掌握,手算一次也是不错的方法,这样才能在考到时马上想出来,实现就不困难了;努力,终于有回报啦!

解题报告:

一.   一道简单题:

题意:选定一个根节点,使得所以子节点的奶牛数乘以它们到根节点的距离的和最小;

分析:-这道题采用的是我原来一直用错的方法,即把子节点的牛加到父节点,让父节点来背这一段距离的锅,这样先走一次dfs就可以枚举边,得到某条边换向之后对结果的影响,即先减去原来这个节点及子节点在这一条路上加过的数,再加上其余节点在转向后要走的路(其余节点的算法就是size[1]-size[x],这就是先把所有节点的牛加到dfs根节点的好处),所以其实这道题是贪心;

亮点:根据对结果的影响贪心;

程序:

#include<iostream>

#include<cstdio>

#include<vector>

const int maxn=100005;

using namespace std;

int size[maxn],c[maxn],n,dis[maxn],sta,fin,len;

long long ans;

vector<int>e[maxn],w[maxn];

void dfs(int x,int f)

{

int len=e[x].size();size[x]=c[x];//第一次访问;

for(int i=0;i<len;i++){

int y=e[x][i],v=w[x][i];

if(y==f)continue;

dis[y]=dis[x]+v;//唯一父亲;//变量

ans+=dis[y]*c[y];//dis已得到,不能用size;

dfs(y,x);

size[x]+=size[y];

}

}

void move(int x,int f)

{

int len=e[x].size();

for(int i=0;i<len;i++){

int y=e[x][i],v=w[x][i];

if(y==f)continue;

if(size[1]-2*size[y]<0)ans+=size[1]*v-2*size[y]*v;//对儿子节点的操作;

move(y,x);

}

}

int main()

{

freopen("A.in","r",stdin);

freopen("A.out","w",stdout);

scanf("%d",&n);

for(int i=1;i<=n;i++)scanf("%d",&c[i]);

for(int i=1;i<n;i++){

scanf("%d %d %d",&sta,&fin,&len);

e[sta].push_back(fin);e[fin].push_back(sta);

w[sta].push_back(len);w[fin].push_back(len);//复制要注意变量

}

dfs(1,0);

move(1,0);

printf("%I64d",ans);

return 0;

}

我看了很久的标程:

#include<map>

#include<set>

#include<cmath>

#include<stack>

#include<queue>

#include<cstdio>

#include<vector>

#include<cstring>

#include<cstdlib>

#include<iostream>

#include<algorithm>

#define mod 998244353

#define pi acos(-1)

#define inf 0x7fffffff

#define ll long long

using namespace std;

ll read()

{

ll x=0,f=1;char ch=getchar();

while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}

while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}

return x*f;

}//读入优化;

int n;

ll ans;

ll c[100005],dis[100005],size[100005];

vector<int> e[100005],w[100005];//动态存链表不容易超内存;

ll dfs(int x,int fa)

{

ll ans=dis[x]*c[x];

size[x]=c[x];

for(int i=0;i<e[x].size();i++)//最好直接保存;

{

int y=e[x][i],v=w[x][i];

if(y==fa)continue;

dis[y]=dis[x]+v;

ans+=dfs(y,x);

size[x]+=size[y];//直接帮背子树距离的锅;

}

return ans;

}

void move(int x,int fa)

{

for(int i=0;i<e[x].size();i++)

{

int y=e[x][i],v=w[x][i];

if(y==fa)continue;//多叉树;

if(size[1]-2*size[y]<0)

{

ans=ans+(size[1]-2*size[y])*v;//这个改变会使ans变小,转一次边;

move(y,x);//一个size是求本来自己的牛数;//1处存总数;

}

}

}//树上求距离

int main()

{

freopen("A.in","r",stdin);

freopen("A.out","w",stdout);

n=read();

for(int i=1;i<=n;i++)

c[i]=read();//ll赋给int不会有问题;

for(int i=1;i<n;i++)

{

int u=read(),v=read(),x=read();

e[u].push_back(v);//双向边

e[v].push_back(u);

w[u].push_back(x);//一一对应

w[v].push_back(x);

}

ans=dfs(1,0);

move(1,0);

cout<<ans<<endl;

return 0;

}

二.   一道更简单题:

题意:每个点等于周围d距离的点的值相加,求最后每个点的值;

分析:根据矩阵的对称性用序列乘法,一个固定不动一个循环一下就ok,注意优化时间复杂度;还是可以结合而且甚至可以交换!

注意:dfs时在等于一就不拓展,不然会多出整整一层,至少3~4的常数,而且本身dfs比较慢里面还有步骤,很可怕,这道题2s测试点也就增加了常数倍,本来3e7的算法常数大了就boom;标程常数还要优一点,多学习;矩阵是不能交换的哦所以总是写在最后,只有序列可以

程序:

#include<iostream>

#include<cstdio>

#include<cstring>

using namespace std;

const int maxn=1000000007;

int n,d,k,a[1005];

long long res[1005],ovo[1005],tmp[1005];

void cf(int pd)

{

tmp[1]=0;

if(pd){

for(int i=1;i<=n;i++,tmp[i]=0){

for(int j=1;j<=n;j++){

int qwq=(i-j+1+n)%n;if(!qwq)qwq=n;

tmp[i]+=res[qwq]*ovo[j]%maxn;

}//原理同正方形矩阵,故可“交换”

tmp[i]%=maxn;}

}

else{

for(int i=1;i<=n;i++,tmp[i]=0){

for(int j=1;j<=n;j++){

int qwq=(i-j+1+n)%n;if(!qwq)qwq=n;

tmp[i]+=res[qwq]*res[j]%maxn;//循环;

}

tmp[i]%=maxn;

}

}

for(int i=1;i<=n;i++)res[i]=(long long)tmp[i];

}

void ef(int u)

{

if(u>>1){//

if(u>>1!=1)ef(u>>1);cf(0);

}

if(u&1&&u!=1)cf(1);

}

int main()

{

freopen("B.in","r",stdin);

freopen("B.out","w",stdout);

scanf("%d %d %d",&n,&d,&k);

for(int i=1;i<=n;i++)scanf("%d",&a[i]);

res[1]=ovo[1]=1;//省去“第一排”;

for(int i=1;i<=d;i++)res[1+i]=res[1-i+n]=ovo[1+i]=ovo[1-i+n]=1;

//向下溢出补一个循环;

ef(k);

for(int i=1;i<=n;i++){

long long ans=0;

for(int j=1;j<=n;j++){

int qwq=(i-j+1+n)%n;if(!qwq)qwq=n;

ans+=res[qwq]*a[j]%maxn;//过程;//顺序

}

printf("%I64d ",ans%maxn);

}

return 0;

}

常数小的标程:语法各种酷炫简洁,只能膜拜;

#include <iostream>

#include <iomanip>

#include <fstream>

#include <stdlib.h>

#include <time.h>

#include<cstring>

#include<cstdio>

#include<vector>

#include<string>

#include<algorithm>

#include <limits.h>

#include<cmath>

#include<map>

#include<queue>

#include<set>

using namespace std;

long long n,d,k;

long long m=1000000007;

void mul(long long a[],long long b[])

{

int i,j;

long long c[1501];

for(i=0;i<n;++i)for(c[i]=j=0;j<n;++j)c[i]+=a[j]*b[i>=j?(i-j):(n+i-j)]%m;

//三目运算简化好帅qwq; //for和运算写一行调试直接跳好厉害       for(i=0;i<n;b[i]=c[i++]%m);

}

long long init[1501],tmp[1501];

int main()

{

freopen("B.in","r",stdin);

freopen("B.out","w",stdout);

long long  i,j;

scanf("%lld%lld%lld",&n,&d,&k);

//k=1;d=1;

for(i=0;i<n;++i)scanf("%lld",&init[i]);

for(tmp[0]=i=1;i<=d;++i)tmp[i]=tmp[n-i]=1;//边for边简化;//对对称的简化;

while(k)//快速幂的方法一定要掌握!

{

if(k&1)mul(tmp,init);//b存结果;//先把现在的乘一次就是init啦;

mul(tmp,tmp);//mul是算幂的意思可以规范化啦,//等于1的时候反正也不会乘啦;

k>>=1;//这样最后的2变1就不用担心了,反正就顺便乘上去,然后直接输出,

//怎么都不会出问题; //从外到里乘;tmp有的,init同步

//2 2^2 2^3,2*2^2,2^4,2,2*2^2*2^4;

}

for(i=0;i<n;++i)if(i)printf(" %lld",init[i]);else printf("%lld",init[i]);

printf("\n");

return 0;

}

三.   最简单的题:

题意:求k mod 1+到k mod n的值;

分析:找规律,很容易发现在商相同的序列里是商为公差的等差数列;

程序:

#include<iostream>

#include<cstdio>

using namespace std;

long long ans,r,k,n,l,cnt,sta;

int main()

{

freopen("C.in","r",stdin);

freopen("C.out","w",stdout);

scanf("%I64d %I64d",&n,&k);

if(n>k)ans+=(n-k)*k;

r=k-1;l=k/2+1;cnt=1;sta=1;

while(1){

ans+=(2*sta+cnt*(r-l))*(r-l+1)/2;

r=l-1;l=k/(++cnt+1)+1;

if(r>0&&l>=0)

sta=k%r;

else break;

if(r==l)break;

}

for(int i=1;i<=l;i++)ans+=k%i;

printf("%I64d",ans);

return 0;

}

不得不说,标程不仅不巧妙还转了很!多!个!弯!

#include <cstdio>

#include <cstring>

#include <cstdlib>

using namespace std;

typedef long long LL;

LL n,m;

LL sum;

int main(void)

{

freopen("C.in","r",stdin);

freopen("C.out","w",stdout);

scanf("%lld%lld",&n,&m);

sum+=(LL)n*m;//剩下的要减;//容易爆ll;

// printf("%I64d\n",sum);

if (n>m) n=m;

//先把数本身加上去,然后把差的减回来,差的就是结合了顺序

//和商的等差数列; 公式去掉相同的以后,可以看出

//2*n-j(l+r)其实就是首项加末项;

LL l,r,j;

for (LL i=1;i<=n;i=r+1)//i:上次处理的数右边的数;

{

j=m/i,l=m/(j+1)+1,r=m/j;//从前向后移动区间,i加了优化没有那么慢

if (r>=n) r=n;//j:商;l:左区间;r:右区间;区间也是数本身

sum-=(LL)(l+r)*(r-l+1)*j/2;

}

printf("%I64d\n",sum);

return 0;

}//只能告诉我们,有的时候可以根据公式再简化出一个很神奇的东西;尤其是mod这种我们可以自己写公式的东西!

转载于:https://www.cnblogs.com/SindarDawn/p/5812389.html

2016.8.27一套简单的题解题报告相关推荐

  1. 攻防世界XCTF-MISC入门12题解题报告

    MISC属于CTF中的脑洞题,简直就是信息安全界的脑筋急转弯.你说它渣,它也有亮点,不好评说.这块最亮眼的入门题就属隐写术,出题人骚的狠.但是我感觉未来其中一个重点,就是大数据安全,从海量流量中捕获恶 ...

  2. 网络流20+4题解题报告(已更前20题)

    链接:网络流20+4题解题报告 代码预览:Github 转载于:https://www.cnblogs.com/water-mi/p/10538858.html

  3. 2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案

    2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案 1.题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. ...

  4. 糖果(2019第十届蓝桥杯省赛C++A组I题) 解题报告(状压dp) Apare_xzc

    糖果(2019第十届蓝桥杯省赛C++A组I题) 解题报告(状压dp) xzc 2019/4/5 试题 I: 糖果 时间限制: 1.0s 内存限制: 256.0MB 本题总分:25分 [问题描述]    ...

  5. 【LeetCode】163.Missing Ranges(Medium)(带锁题)解题报告

    [LeetCode]163.Missing Ranges(Medium)(带锁题)解题报告 题目地址:https://leetcode.com/problems/missing-ranges/(带锁题 ...

  6. LOJ#6103. 「2017 山东二轮集训 Day2」第一题 解题报告

    LOJ#6103. 「2017 山东二轮集训 Day2」第一题 解题报告 前置知识:闭区间上的连续函数的零点存在性定理: 我们定义这样的函数: 定义域为 [ l , r ] ∩ Z [l,r]\cap ...

  7. 攻防世界XCTF-MOBILE入门9题解题报告

    说实话,这几天被逆向的恐怖思维,深深的吓着了,真的要抱腿腿了,叫我失眠了好几晚,我觉得逆向分析是CTF中最难的,求腿腿指点迷津啊,我决定不闷头自己研究了.@欠费烦 感谢大佬提供的帮助,让我有了继续刷下 ...

  8. 攻防世界XCTF-WEB入门12题解题报告

    WEB入门题比较适合信息安全专业大一学生,难度低上手快,套路基本都一样 需要掌握: 基本的PHP.Python.JS语法 基本的代理BurpSuite使用 基本的HTTP请求交互过程 基本的安全知识( ...

  9. 10月9日模拟题解题报告

    PS:昨天月考,极其恶劣的成绩,结果李总在伤口上给我们撒盐,今天搞了个模拟赛--- 1.期末考试 finaltest.cpp/c/pas 1s / 128M [题目描述]  山山同学在期末考试前向他妈 ...

  10. openoj的一个小比赛(F题解题报告)poj3978(dp+素数筛选)

    http://openoj.awaysoft.com:8080/judge/contest/view.action?cid=47#problem/F 一个素数帅选法的题目,才开始直接就套模板结构tle ...

最新文章

  1. Objective C 链式调用
  2. 云炬Android开发报错处理教程 解决Android Studio kotlin等依赖下载慢,下载超时失败的问题
  3. java-Set集合源码学习
  4. 二分求幂,快速求解a的b次幂
  5. JavaScript产生一个n到m之间的随机数
  6. C语言中比较大小的函数模板,C语言中实现模板函数小结 : 不敢流泪
  7. [bzoj1500 维修数列](NOI2005) (splay)
  8. android 崩溃,android 9出现崩溃
  9. 《Docker技术从入门到实践》第1,2章
  10. FFMPEG结构体分析:AVCodecContext
  11. Listener监听器已经Listener的小案例
  12. 062 函数进阶小结
  13. 第一、三、四届(2010、2012、2013)山东省ACM
  14. 【阿里技术】2019年开发者必读!20位阿里技术大牛们帮你列了一份经典书单!
  15. 有限元法 有限差分法 有限体积法
  16. IE重置input file
  17. —— GPS测量原理及应用复习 ——
  18. 推送流程(极光推送)
  19. 如何使用EasyNVR+CDN突破萤石云在直播客户端数量上的限制,做到低成本高性价比的直播
  20. mysql的gis_MySQL的GIS功能

热门文章

  1. 测试环境下将centos6.8升级到centos7的操作记录(转)
  2. [LeetCode] Minimum Window Substring 散列映射问题
  3. Pollen 1.5 发布,Web 投票系统
  4. PySide QtCore.Signal帮助手册
  5. PHP设计模式——观察者模式
  6. [LeetCode] Construct Binary Tree from Preorder and Inorder Traversal 由先序和中序遍历建立二叉树...
  7. Android 使用 TableLayout 布局拉伸宽度
  8. Debian 下配置ssh
  9. 【word】为什么word分两栏的最后一页左边一栏没写完跑到右边去了
  10. 浏览器渲染页面的原理及流程---------重绘与重排(回流)--优化