noip 2012 提高组 day2 部分题解

noip 2012 提高组 day2 部分题解

noip 2012 提高组 day2 部分题解

  这道题有多种解法,我用的是扩展欧几里得算法求到的答案

 1 #include<iostream>
 2 #include<fstream>
 3 #include<cstdio>
 4 using namespace std;
 5 typedef long long ll;
 6 ifstream fin("mod.in");
 7 FILE *fout = fopen("mod.out","w");
 8 void gcd(ll a,ll b,ll& x,ll& y){
 9     if(!b){    x = 1, y = 0;    }
10     else{    gcd(b, a%b, y, x);    y -= x * (a / b);    }
11 }
12 ll a1,b1;
13 ll x1 = 0,y1 = 0;
14 int main(){
15     fin>>a1>>b1;
16     gcd(a1, b1, x1, y1);
17     fprintf(fout,"%ld",(x1 + b1 * 2)%b1);
18     return 0;
19 }

noip 2012 提高组 day2 部分题解

noip 2012 提高组 day2 部分题解

  这道题把第i个人看做一个有序的序列(1、2、3、4....)然后二分

至于求和,就像这么处理:

  noip 2012 提高组 day2 部分题解

接着从前面开始求和。。。

noip 2012 提高组 day2 部分题解

就像这样可以求出每一天的教室使用量,如果1 ~ v天中有哪一天不够用了,就在前半段

查找,如果都足够,就向后面查找,每次不够的时候更新结果result

 1 #include<iostream>
 2 #include<fstream>
 3 #include<cstdio>
 4 #include<cctype>
 5 #include<cstring>
 6 using namespace std;
 7 typedef bool boolean;
 8 FILE *fout = fopen("classroom.out","w");
 9 template <class T> 
10 inline void get(T &u){
11     char x;
12     while(!isdigit(x=getchar()));
13     for( u=x-48; isdigit(x=getchar()); u*=10,u+=(x-48));
14     ungetc(x,stdin);
15 }
16 int *d;
17 int *s;
18 int *t;
19 int *r;
20 int *buf;
21 int m,n;
22 boolean solve(int v){
23     memset(buf, 0, sizeof(int) * (n + 1));
24     int sum = 0;
25     int limit = 0;
26     for(int i = 1;i <= v;i++){
27         buf[s[i]] += d[i];
28         buf[t[i] + 1] -= d[i];
29         limit = max(limit, t[i]);
30     }
31     for(int i = 1;i <= limit;i++){
32         sum += buf[i];
33         if(sum > r[i])    return true;
34     }
35     return false;
36 }
37 int main(){
38     freopen("classroom.in","r",stdin);
39     get(n);
40     get(m);
41     r = new int[(const int)(n + 1)];
42     d = new int[(const int)(m + 1)];
43     s = new int[(const int)(m + 1)];
44     t = new int[(const int)(m + 1)];
45     buf = new int[(const int)(n + 1)];
46     for(int i = 1;i <= n;i++)    get(r[i]);
47     for(int i = 1;i <= m;i++){
48         get(d[i]);
49         get(s[i]);
50         get(t[i]);    
51     }
52     int from = 1;
53     int end = m;
54     int result = 0;
55     while(from <= end){
56         int mid = (from + end) >> 1;
57         if(solve(mid)){
58             result = mid;
59             end = mid - 1;
60         }else from = mid + 1;
61     }
62     if(!result)    fprintf(fout,"0
");
63     else fprintf(fout,"-1
%d
",result);
64     return 0;
65 }