NOIP 2012 Day2
tags:
- 擴展歐幾里得
- 二分答案
- 查分
- 倍增
- 二分答案
- 貪心
- NOIP
categories: - 信息學競賽
- 總結
同余方程
借教室
疫情控制
同余方程
Solution
首先同余式可以轉化為等式.
\[ax\equiv 1\mod b\Leftrightarrow ax+by=1\]
根據擴展歐幾里得定理, 對于式
\[ax+by=k(a,b),k\in \mathbf{R}\]一定存在整數解.然而題面說一定存在解, 也就是說\((a,b)=1\), 然后就可以利用擴展歐幾里得遞歸求得一組解.利用這組解加上取模, 就可以獲得最小整數解.
Code
#include<cstdio> void exgcd(int a,int b,int &x,int &y){if(!b){x=1,y=0;return ;}exgcd(b,a%b,y,x);y-=x*(a/b); }int main(){int a,b,x,y;scanf("%d%d",&a,&b);exgcd(a,b,x,y);printf("%d",(x%b+b)%b);return 0; }借教室
Solution
可以發現近些年 NOIP 總是出二分答案的題.
其實就是給出一些操作, 每次對一定區間減去一個數, 求在哪次操作之后產生了負數.然而可以用線段樹強行做, 也可以用一些巧妙一點的辦法.
- 線段樹, 只需要有區間加操作和查詢區間最小值操作, 一般線段樹可以拿到95分, 還可以用可以各種卡常技巧, zkw線段樹或者是標記永久化來加快.
- 二分一個值\(\text{T}\), 表示前\(\text{T}\)次借教室后會不會出現不合法情況(即某天教室只剩下負數間), 然后用差分借完\(T\)次教室后每一天剩下的教室數.這個一般情況是不會被卡的.注意對于答案的記錄.
Code
#include<cstring> #include<cstdio> #define N 1000055 #define inf 0x3f3f3f3f #define int long long struct Node{int l,r,s;void init(){scanf("%lld%lld%lld",&s,&l,&r);} }s[N];int n,m,d[N]; int qi[N]; int ans;int min(int a,int b){return a<b?a:b; }bool check(int tim){qi[0]=0;for(int i=1;i<=n;++i)qi[i]=d[i]-d[i-1];for(int i=1;i<=tim;++i)qi[s[i].l]-=s[i].s,qi[s[i].r+1]+=s[i].s;int he=0;for(int i=1;i<=n+1;++i){he+=qi[i];if(he<0){ans=min(ans,tim);return false;}}return true; }main(){ans=inf;scanf("%lld%lld",&n,&m);for(int i=1;i<=n;++i)scanf("%lld",&d[i]);for(int i=1;i<=m;++i)s[i].init();int l=1,r=m,mid;while(l<=r){mid=(l+r)>>1;if(!check(mid))r=mid-1;else l=mid+1;}if(l>=m)printf("0");else printf("-1\n%lld",ans);return 0; }疫情控制
并不是很明白為什么一天會出兩道二分答案的題目...
首先二分一個值\(\text{T}\), 表示在\(\text{T}\)時刻內能封鎖這棵樹
還是有一個很重要的貪心策略, 就是一個點在到達根節點之前總是越往上走越好.然后根據倍增確定出每個點在給定時間\(\text{T}\)所到達的最高點(根節點為終點). 必然有一些點到達不了根節點, 那么就讓它來控制這個點; 必然有在不同時間到達根節點的點, 這些點可以去控制根節點的不同沒被控制的子樹; 所以最后找出所有沒有被控制的樹點和能到達根節點的軍隊進行貪心即可.
細節太多了, 很討厭吶.
轉載于:https://www.cnblogs.com/qdscwyy/p/8728111.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的NOIP 2012 Day2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode的二分查找的练习部分总结
- 下一篇: CF 961E Tufurama