NOIP2011提高组day2
NOIP 2011 提高组 Day 2
T1 :
题意:
这道题题意很显然,方法就是利用数学中的二项式定理 : ( x + y ) ^ n = C ( i , n ) * x ^ i * y ^ ( n - i ),i ∈ [ 0 , n ],所以求x ^ n * y ^ m的系数,就是求C( n , k ) * a ^ n * b ^ m再模上10007,注意求C( n , k ) % mod时要求逆元。
代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std;const int mod = 10007;long long fac, vfac, vvfac, facc, M; long long a, b, k, n, m;long long exgcd(long long a1, long long b1, long long &x, long long &y) {if (b1 == 0) {x = 1;y = 0;return b1;} else {long long x0, y0;long long dd = exgcd(b1, a1 % b1, x0, y0);x = y0;y = x0 - (a1 / b1) * y0;return dd;} }long long rv(long long i, long long mo) {long long x, y;exgcd(i, mo, x, y);return (x % mo + mo) % mo; }int main() {freopen("factor.in", "r", stdin);freopen("factor.out", "w", stdout);scanf("%I64d%I64d%I64d%I64d%I64d", &a, &b, &k, &n, &m);fac = 1;facc = 1;M = 1;for (int i = 1; i <= k; i++) M = M * i % mod;for (int i = 1; i <= n; i++) fac = fac * i % mod;for (int i = 1; i <= m; i++) facc = facc * i % mod;vfac = rv(fac, mod);vvfac = rv(facc, mod);long long w = (M % mod * vfac % mod * vvfac % mod) % mod;long long l = 1, r = 1;for (int i = 1; i <= n; i++) l = l * a % mod;for (int i = 1; i <= m; i++) r = r * b % mod;printf("%I64d\n", (l % mod * r % mod * w % mod) % mod);return 0; }
View Code
T2 :
题意:
不难想到这道题求W要用到二分答案,二分的条件也不难想,注意求L到R中有多少个满足W[ i ] >= W的时候可以借助前缀和。
#include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std;const int N = 200001;const long long INF = 1e15 + 1;long long n, m, S, ans = INF, Y; long long w[N], v[N], ll[N], rr[N], sum[N], cnt[N];bool check(long long x) {memset(sum, 0, sizeof(sum));memset(cnt, 0, sizeof(cnt));Y = 0;for (int i = 1; i <= n; i++) {if (w[i] >= x) sum[i] = sum[i - 1] + v[i], cnt[i] = cnt[i - 1] + 1;else sum[i] = sum[i - 1], cnt[i] = cnt[i - 1];}for (int i = 1; i <= m; i++)Y += (cnt[rr[i]] - cnt[ll[i] - 1]) * (sum[rr[i]] - sum[ll[i] - 1]);if (abs(Y - S) <= ans) {ans = abs(Y - S);return true;}return false; }int main() {freopen("qc.in", "r", stdin);freopen("qc.out", "w", stdout);scanf("%I64d%I64d%I64d", &n, &m, &S);long long ma = -1;for (int i = 1; i <= n; i++) {scanf("%I64d%I64d", &w[i], &v[i]);if (w[i] > ma) ma = w[i];}for (int i = 1; i <= m; i++) scanf("%I64d%I64d", &ll[i], &rr[i]);long long lf = 0, rg = ma;while (lf != rg) {long long mid = (lf + rg) >> 1;if (check(mid) && Y <= S) rg = mid;if (check(mid) && Y > S) lf = mid + 1;if (!check(mid) && Y <= S) rg = mid;if (!check(mid) && Y > S) lf = mid + 1;}int mid = (lf + rg) >> 1;check(mid);printf("%I64d\n", ans);return 0; }
View Code
T3 :
题意:
这道题要求的是乘客的总旅行时间最短,不难想到要让每一个乘客旅行时间都最短,所以我们想到可以用贪心算法来求解,所以现在的问题是,我们要怎么使用这些氮气瓶?我们应该给哪些段加速?
首先,如果有这样的一段路,观光车比下一个站点最晚到的一个人还要到得晚,很显然我们该使用加速器了;其次,如果有很多段这样的路段,我们便选择对结果影响最大的一段,就是在下一站下车人数最多的那一段,这样一直找下去,直到氮气用尽或者是不存在这样的路段。
需要用到的数组:
latest[ i ]:站点i乘客最晚到的时间;
arrive[ i ]:观光车最晚到i站点的时间;
next[ i ]:离第i个站点最近的站点满足latest[ i ] >= arrive[ i ](意思就是说从i到next[ i ] - 1的路段都满足观光车到得比游客晚);
sum[ i ]:前i个站中下车的人数;
这是网上找的有批注版的,便于理解:
#include<iostream> #include<cstdio> #include<cmath> using namespace std; int n,m,k; int Di[1005]; int t[10005],a[10005],b[10005]; int arrive[1005],latest[1005]; int sum[1005],next[1005]; int minn,sta; int ans; int maxl; int main() {freopen("bus.in","r",stdin);freopen("bus.out","w",stdout);scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n-1;i++)scanf("%d",&Di[i]);for(int i=1;i<=m;i++){scanf("%d%d%d",&t[i],&a[i],&b[i]);sum[b[i]]++;if(t[i]>latest[a[i]])latest[a[i]]=t[i];}//前缀累加和for(int i=2;i<=n;i++)sum[i]+=sum[i-1];while(1){//每次更新距离后(用了加速器)都要更新arrive[] arrive[1]=0;for(int i=2;i<=n;i++)arrive[i]=max(arrive[i-1],latest[i-1])+Di[i-1];//且要更新next[],因为用了加速器后,有些点是不满足区间条件next[n]=n;for(int i=n-1;i>=1;i--){//满足条件区间连续 1(*) 2 3(*) 4(*) 5(*) 6 7(*) 8 // 3---next[3]-1 3 6 6 6 6 8 8 8 next[i]=next[i+1];if(arrive[i+1]<=latest[i+1])//第i+1个点不满足next[i]=i+1;}//贪心需找区间maxl=1;while(!Di[maxl]&&maxl<=n-1)++maxl;if(maxl==n||k==0)break;//寻找最优区间//i+1--next[i]-1,sum[next[i]]-sum[i]=i+1--for(int i=maxl+1;i<=n-1;i++)if(Di[i]&&sum[next[maxl]]-sum[maxl]<sum[next[i]]-sum[i])maxl=i;if(sum[next[maxl]]-sum[maxl]==0)break;//后面已无乘客int dd=100005;for(int i=maxl+1;i<=next[maxl]-1;i++)dd=min(dd,arrive[i]-latest[i]);//最小时间差,乘客先到,汽车后到dd=min(dd,k);//这段区间中使用加速器,所有乘客都受益,所以不存在人数最多相同区间dd=min(dd,Di[maxl]);k-=dd;//区间没人都受益,受益总和确定Di[maxl]-=dd;} //此时所以bus都比乘客先到达 for(int i=1;i<=m;i++)ans+=abs(arrive[b[i]]-t[i]);//防止没有加速器 ,可能为负cout<<ans<<endl;return 0; }
View Code
这是自己写的:
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std;const int N = 10001;int t[N], a[N], b[N], latest[N], arrive[N], d[N], next[N], sum[N]; int n, m, k, ans;int main() {freopen("bus.in", "r", stdin);freopen("bus.out", "w", stdout);scanf("%d%d%d", &n, &m, &k);for (int i = 1; i <= n - 1; i++) scanf("%d", &d[i]);for (int i = 1; i <= m; i++) {scanf("%d%d%d", &t[i], &a[i], &b[i]);if (t[i] > latest[a[i]]) latest[a[i]] = t[i];sum[b[i]]++;}for (int i = 1; i <= n; i++) sum[i] += sum[i - 1];while (1) {int maxl = 1;arrive[1] = 0;for (int i = 2; i <= n; i++)arrive[i] = max(arrive[i - 1], latest[i - 1]) + d[i - 1];next[n] = n;for (int i = n - 1; i; i--) {next[i] = next[i + 1];if (arrive[i + 1] <= latest[i + 1]) next[i] = i + 1;}while (!d[maxl] && maxl <= n - 1) maxl++;if (maxl == n || k == 0) break;for (int i = maxl + 1; i <= n - 1; i++)if (d[i] && sum[next[maxl]] - sum[maxl] < sum[next[i]] - sum[i]) maxl = i;if (sum[next[maxl]] - sum[maxl] == 0) break;int least = 1e8 + 7;for (int i = maxl + 1; i <= next[maxl] - 1; i++)least = min(least, arrive[i] - latest[i]);least = min(least, k);least = min(least, d[maxl]);k -= least;d[maxl] -= least;}for (int i = 1; i <= m; i++) ans += (arrive[b[i]] - t[i]);printf("%d", ans);return 0; }
View Code
转载于:https://www.cnblogs.com/ganster/p/8833209.html
NOIP2011提高组day2相关推荐
- 洛谷P1003 铺地毯 noip2011提高组day1T1
洛谷P1003 铺地毯 noip2011提高组day1T1 洛谷原题 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n ...
- 【做题记录】[NOIP2011 提高组] 观光公交
P1315 [NOIP2011 提高组] 观光公交 我们想在 \(k\) 次加速每一次都取当前最优的方案加速. 考虑怎样计算对于每一条边如果在当前情况下使用加速器能够使答案减少的大小. 如果当前到达某 ...
- 信息学奥赛一本通 1118:铺地毯 | 1863:【11NOIP提高组】铺地毯 | OpenJudge NOI 1.9 14 | 洛谷 P1003 [NOIP2011 提高组] 铺地毯
[题目链接] ybt 1118:铺地毯 ybt 1863:[11NOIP提高组]铺地毯 OpenJudge NOI 1.9 14:铺地毯 洛谷 P1003 [NOIP2011 提高组] 铺地毯 [题目 ...
- c/c++ 洛谷 P1003 【NOIP2011 提高组】 铺地毯
题目链接 洛谷 P1003 [NOIP2011 提高组] 铺地毯 不想戳的看下图: 样例及解释 数据范围 解题思路: 从后往前找地毯,找到了我就输出并返回. 代码如下: #include <io ...
- 【洛古 P1315】 [NOIP2011 提高组] 观光公交
[NOIP2011 提高组] 观光公交 题目背景 感谢 @Transhumanist 提供的一组 Hack 数据 题目描述 风景迷人的小城 Y 市,拥有 n n n 个美丽的景点.由于慕名而来的游客越 ...
- [NOIP2011 提高组] 铺地毯
题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 nn 张地毯,编号从 11 到 nn.现在将这些地毯按照编号从小到大的顺序 ...
- P1003 [NOIP2011 提高组] 铺地毯
题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到 n.现在将这些地毯按照编号从小到大的顺序平行于 ...
- noip2011提高组day1+day2解题报告
Day1 T1铺地毯https://www.luogu.org/problem/show?pid=1003 [题目分析] 全部读入以后从最后一个往前找,找到一个矩形的范围覆盖了这个点,那这个矩形就是最 ...
- NOIP 2015 提高组 Day2
期望得分:100+10+60=170 实际得分:100+10+35=145 http://www.cogs.pro/cogs/page/page.php?aid=16 T1 跳石头 时间限制:1 s ...
最新文章
- 【Android应用开发】 Android 崩溃日志 本地存储 与 远程保存
- 使用office生成PDF文件
- 老王学linux-ftp
- FCOS: A Simple and Strong Anchor-free Object Detector
- JAVA入门级教学之(关系运算符)
- 【Angular 4】Can't bind to 'ngModel' since it isn't a known property of 'input'
- Android每日一记
- project甘特图导出图片_Project将任务及甘特图导出Excel的方法
- “御用”大数据为你揭秘:故宫,怎么这么“火”?
- uniapp开发微信小程序教程(一)
- S3C2440 蜂鸣器 汇编语言,S3C2440 点亮led灯详解(基于MDK) | 勤奋的小青蛙
- 区块链技术如何让租房市场回归理性?
- 基于SWT组件的IE内核Java简易浏览器
- 只需要MTK工程的bin文件、手机和下载线便可以修改各种手机软件
- Excel#整体增加相同行高的宏命令#
- 盈一指风华,浅梦一程。生命的美丽
- Matlab:数学之美--绘制分形图形
- WIN7登陆界面去掉下面windows 7 旗舰版
- 测试指令和位测试指令的用法-TEST
- 双连通分量(点双连通分量)