[BZOJ 1407][NOI 2002]Savage(中国剩余定理+扩展欧几里得)
2015-04-27 10:02
573 查看
题目链接
http://www.lydsy.com/JudgeOnline/problem.php?id=1407思路
由于此题里n n的范围很小,因此可以直接从小到大暴力枚举洞穴个数m m(注:此题并不满足二分的性质),那么问题转变为一个判定性问题:已知m m,问所有野人在它们的有生之年里是否会出现冲突。直接暴力枚举野人i i和j j,我们要求他们俩第一次相遇的时间x x,容易构造一个同余式(step i −step j )x≡pos j −pos i (modm) (step_i-step_j)x\equiv pos_j-pos_i(\mod m)我们要求的就是这个同余式的最小解x min x_{min}
可以转换为下面的式子
(step i −step j )x+my=pos j −pos i (step_i-step_j)x+my=pos_j-pos_i
由于上面的x,y x,y的系数并不是两两互质,因此需要先对所有的系数和常数除以gcd gcd。可以通过扩展欧几里得找到一个(x 0 ,y 0 ) (x_0,y_0),显然step i −step j gcd(step i −step j ,m) x 0 +mgcd(step i −step j ,m) y 0 =pos j −pos i gcd(step i −step j ,m) \frac{step_i-step_j} {gcd(step_i-step_j,m)}x_0+\frac m {gcd(step_i-step_j,m)} y_0=\frac {pos_j-pos_i} {gcd(step_i-step_j,m)}
显然一个可行解是(gcd(step i −step j ,m)x 0 ,gcd(step i −step j ,m)y 0 ) (gcd(step_i-step_j,m)x_0,gcd(step_i-step_j,m)y_0)
x x的通解满足x=gcd(step i −step j ,m)x 0 +kmgcd(step i −step j ,m) x=gcd(step_i-step_j,m)x_0+k\frac m {gcd(step_i-step_j,m)},若最小的解x min ≤min{age i ,age j } x_{min}\leq \min \{ age_i,age_j\}则表明当前的m m不合法,若枚举完所有的点对(i,j) (i,j)都合法,则表明当前的解m m是合法的。
代码
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #define MAXN 80 using namespace std; struct Node { int val; //键值 int weight; //权值 int frequence; //频率 }node[MAXN]; int n,K; bool cmp(Node a,Node b) { return a.val<b.val; } int f[MAXN][MAXN][MAXN],stack[MAXN],top=0; //边界:f[i][i-1][w]=0,表示点i为根结点,下面无左儿子(i-1为根节点,下面无右儿子),显然f值为0 int sum[MAXN]; //频率的前缀和 int main() { scanf("%d%d",&n,&K); for(int i=1;i<=n;i++) scanf("%d",&node[i].val); for(int i=1;i<=n;i++) scanf("%d",&node[i].weight),stack[++top]=node[i].weight; for(int i=1;i<=n;i++) scanf("%d",&node[i].frequence); sort(stack+1,stack+top+1); for(int i=1;i<=n;i++) node[i].weight=lower_bound(stack+1,stack+top+1,node[i].weight)-stack; sort(node+1,node+n+1,cmp); for(int i=1;i<=n;i++) sum[i]=sum[i-1]+node[i].frequence; memset(f,0x3f,sizeof(f)); for(int i=1;i<=n+1;i++) for(int w=0;w<=n;w++) f[i][i-1][w]=0; for(int w=n;w>=1;w--) for(int i=n;i>=1;i--) for(int j=i;j<=n;j++) for(int k=i;k<=j;k++) //枚举[i,j]这段区间的点对应的子树,该子树以点k作为根节点 { f[i][j][w]=min(f[i][j][w],f[i][k-1][w]+f[k+1][j][w]+K+sum[j]-sum[i-1]); //k本来权值小于K,将其权值变为k if(node[k].weight>=w) f[i][j][w]=min(f[i][j][w],f[i][k-1][node[k].weight]+f[k+1][j][node[k].weight]+sum[j]-sum[i-1]); //k的权值本身就大于等于K,因此可以不变 } int ans=0x3f3f3f3f; for(int w=0;w<=n;w++) ans=min(ans,f[1] [w]); printf("%d\n",ans); return 0; }
相关文章推荐
- bzoj 1407: [Noi2002]Savage【扩展欧几里得+中国剩余定理】
- 【扩展欧几里得】Bzoj 1407: [Noi2002]Savage
- BZOJ1407 [Noi2002]Savage 【扩展欧几里得】
- 【扩展欧几里得】Bzoj 1407: [Noi2002]Savage
- bzoj [Noi2002]Savage 扩展欧几里得
- bzoj [Noi2002]Savage 扩展欧几里得
- [BZOJ1407][NOI2002]Savage(扩展欧几里德)
- BZOJ_P1407&Codevs_P1747 [NOI2002]Savage(数论+扩展欧几里得)
- BZOJ 1407: [Noi2002]Savage 扩展欧几里得
- BZOJ 1407: [Noi2002]Savage( 数论 )
- 【BZOJ 1407】 [Noi2002]Savage
- BZOJ1407_NOI2002_荒岛野人_Savage_C++
- 【bzoj1407】 Noi2002—Savage
- [BZOJ1407][NOI2002]Savage(扩欧)
- BZOJ1407: [Noi2002]Savage
- bzoj1407: [Noi2002]Savage
- bzoj1407[Noi2002] Savage
- 【bzoj 1407】【Noi2002】Savage
- BZOJ_1407_[Noi2002]Savage_EXGCD
- [BZOJ1407][Noi2002]Savage