NOIP模拟题17.9.26
B 君的任务(task)
【题目描述】
与君初相识,犹如故人归。
B 君看到了Z 君的第一题,觉得很难。
于是自己出了一个简单题。
你需要完成n 个任务,第i 任务有2 个属性ai; bi。其中ai 是完成这
个任务所需要花费的时间,bi 为如果你在t 时间完成该任务,那么你受到的
损失便是bit。
初始时间是0,你最终收到的损失等于每个任务造成的损失之和,你需
要最小化自己受到的损失。
你只能一个任务接着一个任务的完成,不能同时做多个任务,所以说相
当于你只需要决定一个任务完成的顺序。
【输入格式】
第一行一个整数n。
以下n 行,每行两个整数ai; bi。
【输出格式】
一行一个整数表示答案。
【样例输入】
4
1 4
2 3
3 2
4 1
【样例输出】
35
【数据规模与约定】
对于100% 的数据,满足1 n 105; 0 ai 103; 0 bi 103。
对于30% 的数据,满足1 n 10。
对于70% 的数据,满足1 n 103。
数据没有梯度。
【题解】
国王游戏弱化版。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 7 inline void read(long long &x) 8 { 9 x = 0;char ch = getchar(), c = ch; 10 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 11 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 12 if(c == '-')x = -x; 13 } 14 15 const long long INF = 0x3f3f3f3f; 16 const long long MAXN = 1000000 + 10; 17 18 struct Node 19 { 20 long long a,b; 21 Node(long long _a, long long _b){a = _a;b = _b;} 22 Node(){} 23 }node[MAXN]; 24 25 long long cmp(Node t1, Node t2) 26 { 27 return t1.a * t2.b < t2.a * t1.b; 28 } 29 30 long long n; 31 long long T, ans; 32 33 int main() 34 { 35 read(n); 36 for(register long long i = 1;i <= n;++ i) 37 read(node[i].a), read(node[i].b); 38 std::sort(node + 1, node + 1 + n, cmp); 39 for(register long long i = 1;i <= n;++ i) 40 { 41 T += node[i].a; 42 ans += T * node[i].b; 43 } 44 printf("%lld", ans); 45 return 0; 46 }
B 君的病症(ocd)
【题目描述】
享国之日浅,国家无事。
B 君看到了Z 君的第二题,觉得很难。
于是自己出了一个简单题。
大A 是一名强迫症患者,现在他要给一群带颜色的珠子排成一列,现
在有n 种颜色,其中第i 种颜色的珠子有ai 个。要求排列中第i 种颜色
珠子的所有珠子,一定要排在第i + 1 种颜色的第一个和最后一个珠子之
间。问有多少种排列珠子的方案,因为方案数会很大,所以请输出答案对
1000000007 取模之后的结果。
【输入格式】
第一行一个整数n。
以下n 行,每行一个整数ai。
【输出格式】
一行一个整数表示答案。
【样例输入】
3
2
4
4
【样例输出】
168
【数据规模与约定】
对于100% 的数据,满足1 n 104; 2 ai 15。
对于70% 的数据,满足1 n 102。
【题解】
会了上次模拟的那个这个也会,详见上一篇NOIP模拟博客
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 7 inline void read(long long &x) 8 { 9 x = 0;char ch = getchar(), c = ch; 10 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 11 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 12 if(c == '-')x = -x; 13 } 14 15 const long long INF = 0x3f3f3f3f; 16 const long long MAXN = 300000 + 10; 17 const long long MOD = 1000000007; 18 19 long long n,num[MAXN],sum[MAXN],f[MAXN]; 20 21 long long pow(long long a, long long b) 22 { 23 long long r = 1, base = a%MOD; 24 for(;b;b >>= 1) 25 { 26 if(b & 1)r *= base, r %= MOD; 27 base *= base, base %= MOD; 28 } 29 return r; 30 } 31 32 long long ni(long long a) 33 { 34 return pow(a, MOD - 2); 35 } 36 37 long long C(long long n, long long m) 38 { 39 return f[n] * ni(f[n - m])%MOD * ni(f[m])%MOD; 40 } 41 42 int main() 43 { 44 read(n); 45 for(register long long i = 1;i <= n;++ i) 46 read(num[i]), sum[i] = sum[i - 1] + num[i]; 47 f[0] = 1; 48 for(register long long i = 1;i <= MAXN;++ i) 49 f[i] = f[i - 1] * i % MOD; 50 long long ans = 1; 51 for(register long long i = 2;i <= n;++ i) 52 ans = ans * C(sum[i] - 2, num[i] - 2) % MOD; 53 printf("%lld", ans); 54 return 0; 55 }
B 君的方差(variance)
【题目描述】
相逢是问候,分手是祝愿。
B 君看到了Z 君的第三题,觉得很难。
于是自己出了一个简单题。
有一个长度为n 的数组faig,下标从1 开始。你需要支持2 种操作。
1. 1 x y,将第x 个元素修改为y。
2. 2 l r,询问下标l 到r 之间所有数的方差,因为方差可能不是整数,
所以输出时请乘(r l + 1)2 转换成整数输出。
【输入格式】
第一行两个整数n;m,表示数组长度是n,一共有m 个操作。
第二行n 个数,表示ai。
接下来每行一个操作,描述如题目所述。
【输出格式】
对于每个询问操作,输出询问结果。
【样例输入】
4 4
1 2 3 4
2 1 4
1 2 4
2 1 4
2 2 4
【样例输出】
20
24
2
【数据规模与约定】
对于100% 的数据,满足1 n;m 216,数组中的元素0 ai; x 104,
所有下标合法1 x; l; r n。
对于50% 的数据,满足1 n;m 28。
数据没有梯度。
【题解】
化一下式子,线段树/树状数组裸题
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 7 inline void read(long long &x) 8 { 9 x = 0;char ch = getchar(), c = ch; 10 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 11 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 12 if(c == '-')x = -x; 13 } 14 15 const long long INF = 0x3f3f3f3f; 16 const long long MAXN = 100000 + 10; 17 18 long long sum[MAXN << 2], fangsum[MAXN << 2], n, num[MAXN], m; 19 20 void build(long long o = 1, long long l = 1, long long r = n) 21 { 22 if(l == r) 23 { 24 sum[o] = num[l]; 25 fangsum[o] = num[l] * num[l]; 26 return; 27 } 28 long long mid = (l + r) >> 1; 29 build(o << 1, l, mid); 30 build(o << 1 | 1, mid + 1, r); 31 sum[o] = sum[o << 1] + sum[o << 1 | 1]; 32 fangsum[o] = fangsum[o << 1] + fangsum[o << 1 | 1]; 33 } 34 35 void modify(long long p, long long k, long long o = 1, long long l = 1, long long r = n) 36 { 37 if(p == l && l == r) 38 { 39 sum[o] = k; 40 fangsum[o] = k * k; 41 return; 42 } 43 long long mid = (l + r) >> 1; 44 if(p <= mid) modify(p, k, o << 1, l, mid); 45 else modify(p, k, o << 1 | 1, mid + 1, r); 46 sum[o] = sum[o << 1] + sum[o << 1 | 1]; 47 fangsum[o] = fangsum[o << 1] + fangsum[o << 1 | 1]; 48 } 49 50 long long askfangsum(long long ll, long long rr, long long o = 1, long long l = 1, long long r = n) 51 { 52 if(ll <= l && rr >= r)return fangsum[o]; 53 long long mid = (l + r) >> 1; 54 long long sum1 = 0, sum2 = 0; 55 if(mid >= ll)sum1 = askfangsum(ll, rr, o << 1, l, mid); 56 if(mid < rr) sum2 = askfangsum(ll, rr, o << 1 | 1, mid + 1, r); 57 return sum1 + sum2; 58 } 59 60 long long asksum(long long ll, long long rr, long long o = 1, long long l = 1, long long r = n) 61 { 62 if(ll <= l && rr >= r)return sum[o]; 63 long long mid = (l + r) >> 1; 64 long long sum1 = 0, sum2 = 0; 65 if(mid >= ll)sum1 = asksum(ll, rr, o << 1, l, mid); 66 if(mid < rr) sum2 = asksum(ll, rr, o << 1 | 1, mid + 1, r); 67 return sum1 + sum2; 68 } 69 70 int main() 71 { 72 read(n);read(m); 73 for(register long long i = 1;i <= n;++ i) 74 read(num[i]); 75 build(); 76 register long long tmp, l, r; 77 for(register long long i = 1;i <= m;++ i) 78 { 79 read(tmp), read(l), read(r); 80 if(tmp == 1) 81 modify(l, r); 82 else if(tmp == 2) 83 { 84 long long fang = askfangsum(l, r); 85 long long he = asksum(l, r); 86 printf("%lld\n", fang * (r - l + 1) + (he * he) - 2 * he * he); 87 } 88 } 89 return 0; 90 }