小L的二叉树
【题目描述】
勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利。但是,小L对数据结构的掌握实在十分渣渣。
所以,小L当时卡在了二叉树。 在计算机科学中,二叉树是每个结点最多有两个子结点的有序树。通常子结点被称作“左孩子”和“右孩子”。二叉树被用作二叉搜索树和二叉堆。随后他又和他人讨论起了二叉搜索树。什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树。设key[p]表示结点p上的数值。对于其中的每个结点p,若其存在左孩子lch,则key[p] > key[lch];若其存在右孩子rch,则key[p] < key[rch];注意,本题中的二叉搜索树应满足对于所有结点,其左子树中的key小于当前结点的key,其右子树中的key大于当前结点的key。(因为小L十分喜欢装xx,所以这里他十分装xx的给大家介绍了什么是二叉树和二叉搜索树)。 可是善于思考的小L不甘于只学习这些基础的东西。他思考了这样一个问题:现在给定一棵二叉树,可以任意修改结点的数值。修改一个结点的数值算作一次修改,且这个结点不能再被修改。若要将其变成一棵二叉搜索树,且任意时刻结点的数值必须是整数(可以是负整数或0),所要的最少修改次数。 这一定难不倒聪明的你吧!如果你能帮小L解决这个问题,也许他会把最后的资产分给你1/16哦!
【输入格式】 第一行一个正整数n表示二叉树节点数。节点从1~n进行编号。 第二行n个正整数用空格分隔开,第i个数ai表示结点i的原始数值。 此后n - 1行每行两个非负整数fa, ch,第i + 2行描述结点i + 1的父亲编号fa,以及父子关系ch,(ch = 0 表示i + 1为左儿子,ch = 1表示i + 1为右儿子)。 为了让你稍微减轻些负担,小L规定:结点1一定是二叉树的根哦!
【输出格式】 仅一行包含一个整数,表示最少的修改次数。
【样例输入】 3 2 2 2 1 0 1 1
【样例输出】 2
【数据范围】
20 % :n <= 10 , ai <= 100.
40 % :n <= 100 , ai <= 200
60 % :n <= 2000 .
100 % :n <= 10 ^ 5 , ai < 2 ^ 31.


把中序遍历映射成非严格上升的然后求LIS就可以了。
a[i]-a[j] <= i-j ==> a[i]-i <= a[j]-j

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
typedef long long LL;
template <class T> inline void read(T &x)
{x = 0;T flag = 1;char ch = (char)getchar();while(ch<'0' || ch>'9'){if(ch == '-') flag = -1;ch = (char)getchar();}while(ch>='0' && ch<='9'){x = (x<<1) + (x<<3) + ch - '0';ch = (char)getchar();}x *= flag;
}
template <class T> T gcd(T a,T b) { return !b?a:gcd(b,a%b); }
const int INF=0x3f3f3f3f;
const int maxn = 100005;
struct Node
{int ch[2];int val;
}node[maxn];
#define ch(x,d) node[x].ch[d]
#define val(x) node[x].val
int a[maxn];
int n;
void in_order(int root)
{if(!root) return;in_order(ch(root,0));a[++n] = val(root);a[n] -= n;in_order(ch(root,1));
}
inline void init()
{read(n);for(int i=1;i<=n;i++) read(val(i));for(int i=2;i<=n;i++){int fa,id;read(fa); read(id);ch(fa,id) = i;}n = 0;in_order(1);
}
vector <int> d;
int work()
{for(int i=1;i<=n;i++){vector <int> ::iterator it = upper_bound(d.begin(),d.end(),a[i]);if(it == d.end()) d.push_back(a[i]);else (*it) = a[i];}return d.size();
}
int main()
{freopen("tree.in","r",stdin);freopen("tree.out","w",stdout);init();int ans = work();printf("%d",n - ans);return 0;
}

小L的牛栏
【题目描述】 小L通过泥萌的帮助,成功解决了二叉树的修改问题,并因此写了一篇论文, 成功报送了叉院(羡慕不?)。勤奋又勤思的他在研究生时期成功转系,考入了北京大学光华管理学院!毕业后,凭着自己积累下的浓厚经济学与计算机学的基础,成功建设了一个现代化奶牛场! 奶牛们十分聪明,于是在牛场建围栏时打算和小L斗智斗勇!小L有N种可以建造围栏的木料,长度分别是l1,l2„lN,每种长度的木料无限。
修建时,他将把所有选中的木料拼接在一起,因此围栏的长度就是他使用的木料长度之和。但是聪明的小L很快发现很多长度都是不能由这些木料长度相加得到的,于是决定在必要的时候把这些木料砍掉一部分以后再使用。
不过由于小L比较节约,他给自己规定:任何一根木料最多只能削短M米。当然,每根木料削去的木料长度不需要都一样。不过由于测量工具太原始,小L只能准确的削去整数米的木料,因此,如果他有两种长度分别是7和11的木料,每根最多只能砍掉1米,那么实际上就有4种可以使用的木料长度,分别是6, 7,10, 11。
因为小L相信自己的奶牛举世无双,于是让他们自己设计围栏。奶牛们不愿意自己和同伴在游戏时受到围栏的限制,于是想刁难一下小L,希望小L的木料无论经过怎样的加工,长度之和都不可能得到他们设计的围栏总长度。不过小L知道,如果围栏的长度太小,小L很快就能发现它是不能修建好的。因此她希望得到你的帮助,找出无法修建的最大围栏长度。 这一定难不倒聪明的你吧!如果你能帮小L解决这个问题,也许他会把最后的资产分给你1/8哦!
【输入格式】
输入的第一行包含两个整数N, M,分别表示木料的种类和每根木料削去的最大值。以下各行每行一个整数li(1< li< 3000),表示第i根木料的原始长度。
【输出格式】
输出仅一行,包含一个整数,表示不能修建的最大围栏长度。如果任何长度的围栏都可以修建或者这个最大值不存在,输出-1。
【样例输入】 2 1 7 11
【数据范围】
40 % :1< N<10, 0< M< 300
100 % :1< N< 100, 0< M< 3000


由于如果选定一个最小的可以得到的长度,那么任意当前长度加上若干个最短长度都是可以得到的。
那么dp[i]表示长度模为i的最短长度。
也就是说如果模意义下dp[i]是最小的可以表示的长度,小于它的都不可以被表示,那么ans = max{0<=i < mod | dp[i]} - mod

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
typedef long long LL;
template <class T> inline void read(T &x)
{x = 0;T flag = 1;char ch = (char)getchar();while(ch<'0' || ch>'9'){if(ch == '-') flag = -1;ch = (char)getchar();}while(ch>='0' && ch<='9'){x = (x<<1) + (x<<3) + ch - '0';ch = (char)getchar();}x *= flag;
}
template <class T> T gcd(T a,T b) { return !b?a:gcd(b,a%b); }
const int INF=0x3f3f3f3f;
const int maxn = 3005;
const int N = 3000;
bool vis[maxn];
int stick[maxn],cnt,mod;
int n,m;
inline void init()
{read(n); read(m);for(int i=1;i<=n;i++){int tmp;read(tmp);for(int j=0;j<=min(m,tmp-1);j++) vis[tmp-j] = true;}for(int i=1;i<=N;i++) if(vis[i]) stick[++cnt] = i;if(stick[1] == 1) { printf("-1"); exit(0); }else mod = stick[1];
}
int dis[maxn];
bool inque[maxn];
queue <int> que;
void spfa()
{while(!que.empty()) que.pop();memset(dis,0x3f,sizeof(dis));memset(inque,0x00,sizeof(inque));que.push(0); inque[0]=true; dis[0]=0;while(!que.empty()){int u = que.front(); que.pop(); inque[u]=false;for(int i=2;i<=cnt;i++){int v = (u + stick[i]) % mod;if(dis[v] > dis[u] + stick[i]){dis[v] = dis[u] + stick[i];if(inque[v]) continue;inque[v] = true;que.push(v);}}}
}
int work()
{int ans = 0;for(int i=0;i<mod;i++) smax(ans,dis[i]);return ans - mod;
}
int main()
{freopen("bullpen.in","r",stdin);freopen("bullpen.out","w",stdout);init();spfa();int ans = work();printf("%d",ans);return 0;
}

小L的珍珠挂饰
【题目描述】 小L通过泥萌的帮助,成功解决了牛栏的修建问题。奶牛们觉得主人非常厉害,于是再也不敢偷懒,母牛们奋力挤奶,生娃。子子孙孙无穷匮也!小L于是成为了一代富豪! 但是一直困扰小L的就是单身问题!小L经过长久的寻觅,小L终于找到了一个心仪的漂亮妹子。于是,小L打算在520那天给妹子一个惊喜!(虽然小L很节约,但是对妹子还是很阔绰的!) 小L决定用K种珍珠为妹子做一串举世无双的珍珠垂饰。珍珠垂饰是由珍珠连接而成的,其长度可以认为就是珍珠垂饰上珍珠的个数。小L现在腰缠万贯,每种珍珠他都拥有N颗。根据将珍珠垂饰打开后珍珠不同的排列顺序可以区别不同种类的项链。现在,小L好奇自己可以组成多少种长度为1至N的不同的珍珠垂饰?当然,为显富有,每串珍珠垂饰都要必须由K种珍珠连成。 答案取模1234567891。 这一定难不倒聪明的你吧!如果你能帮小L解决这个问题,也许他会把最后的资产分给你1/4哦! 【输入格式】
输入包含多组数据。第一行是一个整数T,表示测试数据的个数。每组数据占一行,包含两个整数N和K,用一个空格隔开。
【输出格式】
每组数据输出仅一行,包含一个整数,表示项链的种类数。
【样例输入】 2 2 1 3 2
【样例输出】 2 8
【数据范围】
40 % :1<= N<=100000, 0<=K<=30
70 % :1<= N<= 1000000000, 0<=K<=30时限 :1000ms
80%~100% :T <= 10, 1<= N<= 1000000000, 0<=K<=30 时限:50ms


前70%:
dp(i,j) = dp(i-1,j) * j + dp(i-1,j-1) * j
用矩阵快速幂转移,可以求前缀和,也可以改变dp的意义,直接表示前缀和。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned U;
template <class T> inline void read(T &x)
{x = 0;T flag = 1;char ch = (char)getchar();while(ch<'0' || ch>'9'){if(ch == '-') flag = -1;ch = (char)getchar();}while(ch>='0' && ch<='9'){x = (x<<1) + (x<<3) + ch - '0';ch = (char)getchar();}x *= flag;
}
template <class T> T gcd(T a,T b) { return !b?a:gcd(b,a%b); }
const int maxn = 33;
const U mod = 1234567891;
int N,K;
struct Matrix
{U w[maxn][maxn];Matrix () { memset(w,0,sizeof(w)); }Matrix operator * (const Matrix &t){Matrix ret;for(int i=1;i<=K+1;i++)for(int p=1;p<=K+1;p++) if(w[i][p])for(int j=1;j<=K+1;j++)(ret.w[i][j] += (U) ((ULL) w[i][p] * t.w[p][j] % mod)) %= mod;return ret;}void operator *= (Matrix &t) { (*this) = t * (*this); }
};
Matrix quick_exp(Matrix a,int p)
{Matrix ans;for(int i=1;i<=K+1;i++) ans.w[i][i] = 1;while(p){if(p&1) ans *= a;p >>= 1;a *= a;}return ans;
}
int main()
{freopen("pearl.in","r",stdin);freopen("pearl.out","w",stdout);int T; read(T);while(T--){read(N); read(K);if(!K) { printf("0\n"); continue; }Matrix ans; ans.w[1][1] = 1; ans.w[K+1][1] = K==1? 1 : 0; // start with S1 = 0 for dp(1,K) = 0Matrix delta;for(int k=1;k<=K;k++) delta.w[k][k-1] = delta.w[k][k] = k;delta.w[1][0] = 0; delta.w[K+1][K-1] = delta.w[K+1][K] = K; delta.w[K+1][K+1] = 1;delta = quick_exp(delta,N-1);ans *= delta;printf("%u\n",ans.w[K+1][1]);}return 0;
}

100%: 容斥原理+等比数列求和
如果直接是k^n,那么只有k-1种颜色的多计算,同时减去k-1的时候又多减了只有k-2个的情况,容斥解决。
由于答案是长度为1~n的方案数总和,那么就用等比数列求每一项的和,再容斥即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned U;
template <class T> inline void read(T &x)
{x = 0;T flag = 1;char ch = (char)getchar();while(ch<'0' || ch>'9'){if(ch == '-') flag = -1;ch = (char)getchar();}while(ch>='0' && ch<='9'){x = (x<<1) + (x<<3) + ch - '0';ch = (char)getchar();}x *= flag;
}
template <class T> T gcd(T a,T b) { return !b?a:gcd(b,a%b); }
const int INF=0x3f3f3f3f;
const int maxn = 35;
const int N = 32;
const U mod = 1234567891u;
U C[maxn][maxn];
U inv[maxn];
inline void init()
{C[0][0] = 1;C[1][0] = C[1][1] = 1;for(int i=2;i<=N;i++)for(int j=0;j<=i;j++)C[i][j] = ((j>=1? C[i-1][j-1] : 0) + C[i-1][j]) %mod;inv[1] = 1;for(int i=2;i<=N;i++) inv[i] = (ULL)(mod-mod/i)*inv[mod%i]%mod;
}
U quick_exp(U a,int p)
{if(!p) return 1;U tmp = quick_exp(a,p>>1);tmp = (ULL)tmp*tmp %mod;if(p&1) return (ULL)tmp*a%mod;else return tmp;
}
U geometric(U q,int n)
{if(q == 1) return n%mod;else return (ULL)q*inv[q-1]%mod*((quick_exp(q,n)+mod-1)%mod)%mod;
}
U work(int n,int k)
{U ret = 0;for(int i=0;i<k;i++){U tmp = (ULL) C[k][i] * geometric(k-i,n) % mod;if(i&1) ret = (ret + mod - tmp) % mod;else (ret += tmp) %= mod;}return ret;
}
int main()
{freopen("pearl.in","r",stdin);freopen("pearl.out","w",stdout);init();int T; read(T);while(T--){int n,k;read(n); read(k);U ans = work(n,k);printf("%u\n",ans);}return 0;
}

NOIP模拟题 2016.11.15 [LIS] [spfa] [同余最短路] [矩阵快速幂] [容斥原理] [数学]相关推荐

  1. 【NOIP模拟题】【DP】【同余最短路】【暴力剪枝】2016.11.15 第二题 小L的牛栏 题解

    小L的牛栏 [题目描述] 小L通过泥萌的帮助,成功解决了二叉树的修改问题,并因此写了一篇论文, 成功报送了叉院(羡慕不?).勤奋又勤思的他在研究生时期成功转系,考入了北京大学光华管理学院!毕业后,凭着 ...

  2. 【jzoj5078】【GDOI2017第三轮模拟day2】【魔法咒语】【ac自动机】【矩阵快速幂】

    题目大意 解题思路 对非法串构ac自动机,对于l较小的情况,设f[i][j]表示长度为i,在ac自动机上j点的方案数,直接dp即可. 对于加入串len<=2的情况,对于每个j拆成两个点矩阵快速幂 ...

  3. 闵梓轩大佬のnoip模拟题D1 总结 2017/10/26

    背景 题目概括 T1 题面 分析 90分算法 满分算法 T2 题面 分析 部分分算法 满分算法 满分代码 T3 题面 分析 代码 总结 背景 这道题目是去年的金牌大佬闵梓轩在一年前出的一套noip模拟 ...

  4. 15年第六届蓝桥杯第九题_(矩阵快速幂优化的动态规划)

    垒骰子 赌圣atm晚年迷恋上了垒骰子,就是把骰子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体. 经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥! 我们先来规范一下骰子:1 的 ...

  5. [3.3训练赛]One-Dimensional(矩阵快速幂),Freda的迷宫(无向图强连通分量+并查集),一道防AK好题

    文章目录 T1:One-Dimensional title solution code T2:[NOIP模拟赛]Freda的迷宫 title solution code T3:[NOIP模拟赛]一道防 ...

  6. 又见斐波那契~矩阵快速幂入门题

    链接:https://www.nowcoder.com/acm/contest/105/G 来源:牛客网 题目描述 这是一个加强版的斐波那契数列. 给定递推式 求F(n)的值,由于这个值可能太大,请对 ...

  7. 20181023(模拟+矩阵快速幂及推公式+最短路+不知道什么DP)

    NOIP欢乐%你赛 1. 小澳的方阵 (matrix.cpp/c/pas) [题目描述] 小澳最近迷上了考古,他发现秦始皇的兵马俑布局十分有特点,热爱钻研的小澳打算在电脑上还原这个伟大的布局. 他努力 ...

  8. 51nod 1113 矩阵快速幂 模板题

    1113 矩阵快速幂 基准时间限制:3 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注 给出一个N * N的矩阵,其中的元素均为正整数.求这个矩阵的M次方.由于M次方的计 ...

  9. [CSP-S模拟测试]:涂色游戏(DP+组合数+矩阵快速幂)

    题目描述 小$A$和小$B$在做游戏. 他们找到了一个$n$行$m$列呈网格状的画板.小$A$拿出了$p$支不同颜色的画笔,开始在上面涂色.看到小$A$涂好的画板,小$B$觉得颜色太单调了,于是把画板 ...

最新文章

  1. py_innodb_page_info.py 脚本下载
  2. JQuery 获取自身的HTml代码
  3. Python3读取HTML文件
  4. LOG4J日志级别详解
  5. 洛谷——P1194 买礼物
  6. 经桥科技与湖南文化艺术产业集团合力打造“网乐潇湘”
  7. 开源贡献 计算_使用此网站为开源做贡献
  8. python123九宫格输入法_《啊哈C语言-2016最新修正版》.pdf
  9. C++ 集成和派生练习题解答
  10. 闪耀在UNIX传奇往事中的启示,UNIX见证者带你一览究竟
  11. 服务器安全配置常用软件
  12. java gb28181网关_视频网关GB28181协议转换解决方案
  13. Win10系统默认播放器一直被修改怎么解决
  14. 峰瑞资本李丰:共享经济如何改造专业且非标准化的服务业
  15. Exp6 信息搜集与漏洞扫描 ——20164316张子遥
  16. android切换夜间模式吗,Android切换夜间模式
  17. Imitation Learning
  18. 201208197PM-Error on Unable to obtain lock on *.lok . Server may already be running
  19. 互联网时代,怎么做到真正的信息安全?
  20. 再谈如何学习Linux,一线Linux专家学习经验谈

热门文章

  1. 提起2013,我所领悟到的
  2. 你是什么时候对深度学习失去信心的?
  3. 苹果app上架流程之傻瓜式教程剖析
  4. PM该如何调动员工的积极性?
  5. 网络安全专业就业怎么样呢?
  6. windows下svn备份
  7. 申请微信支付相关事宜
  8. PIC单片机实现二进制码与压缩BCD码的相互转换
  9. 趣未来科技董事长黄婵娇:专注创新研发,把公司当做科研机构来运作!
  10. 电脑桌面云便签账号怎么更换绑定邮箱?