首页 > 代码库 > NOIP2013 题解

NOIP2013 题解

转圈游戏

  题解:快速幂

 1 #include <cstdio> 2  3 int n, m, k, x; 4  5 inline long long QuickPow(int a, int k, int MOD){ 6     long long base = a, ret = 1; 7     while (k){ 8         if (k&1) ret = (ret*base)%MOD; 9         base = (base*base)%MOD, k >>= 1;10     }11     return ret;12 }13 14 int main(){15     scanf("%d %d %d %d", &n, &m, &k, &x);16     printf("%lld\n", (x%n+(m%n)*QuickPow(10, k, n)%n)%n);17 }
circle.cpp

 

火柴排队

  题解:求逆序对(因为写不来归排就写的树状数组,怕TLE就蛋疼的加了一个读入优化)

 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5  6 const int MAXN =  100000+10; 7 const int MOD = 99999997; 8  9 int n, ans, c[MAXN], d[MAXN];10 char cc;11 12 struct Match{13     int v, n;14 15     friend bool operator < (const Match& A, const Match& B){16         return A.v<B.v;17     }18 }a[MAXN], b[MAXN];19 20 inline void add(int p, int v){21     while (p<=n)22         d[p] += v, p += (p&(-p));23 }24 25 inline int sum(int p){26     int ret = 0;27     while (p>0)28         ret += d[p], p -= (p&(-p));29     return ret;30 }31 32 inline int NextInt(){33     int ret = 0;34     do cc = getchar();35     while (cc<48 || cc>57);36     do ret *= 10, ret += (cc-48), cc = getchar();37     while (48<=cc && cc<=57);38     return ret;39 }40 41 int main(){42     memset(d, 0, sizeof(0));43     n = NextInt(), ans = 0;44     for (int i=0; i<n; i++)45         a[i].v = NextInt(), a[i].n = i+1;46     sort(a, a+n);47     for (int i=0; i<n; i++)48         b[i].v = NextInt(), b[i].n = i+1;49     sort(b, b+n);50     51     for (int i=0; i<n; i++)52         c[a[i].n] = b[i].n;53     54     for (int i=1; i<=n; i++)55         add(c[i], 1), 56         ans = (ans+i-sum(c[i]))%MOD;57     printf("%d\n", ans);58 }
match.cpp

 

货车运输

  题解:先建一个最大生成树,再用lca乱搞一下就好了

  1 #include <cstdio>  2 #include <cstring>  3 #include <algorithm>  4 using namespace std;  5   6 const int MAXL = 20;  7 const int MAXN = 10000+10;  8 const int MAXM = 50000+10;  9 const int INF = 0x3f3f3f3f; 10  11 int n, m, f[MAXN], nimo[MAXN][MAXL], an[MAXN][MAXL], dep[MAXN]; 12 bool vis[MAXN]; 13 char c; 14  15 struct Edge{ 16     int d, to; 17     Edge *next; 18 }e[MAXM], *head[MAXN]; 19  20 struct Bary{ 21     int u, v, d; 22  23     friend bool operator < (const Bary& A, const Bary& B){ 24         return A.d>B.d; 25     } 26 }bd[MAXM]; 27  28 inline int NextInt(){ 29     int ret = 0; 30     do c = getchar(); 31     while (c<48 || c>57); 32     do ret *= 10, ret += (c-48), c = getchar(); 33     while (48<=c && c<=57); 34     return ret; 35 } 36  37 inline int find(int x){ 38     return x==f[x] ? x : f[x]=find(f[x]); 39 } 40  41 int ne = 0; 42 inline void AddEdge(int f, int t, int d){ 43     e[ne].to = t, e[ne].d = d; 44     e[ne].next = head[f]; 45     head[f] = e + ne++; 46 } 47  48 inline void Add(int u, int v, int d){ 49     f[find(u)] = find(v);  50     AddEdge(u, v, d), AddEdge(v, u, d); 51 } 52  53 inline void BuildTree(int x){ 54     vis[x] = true; 55     for (Edge *p=head[x]; p; p=p->next) 56         if (!vis[p->to]) 57             an[p->to][0] = x, nimo[p->to][0] = p->d, dep[p->to] = dep[x]+1, BuildTree(p->to); 58 } 59  60 inline int swim(int &x, int ht){ 61     int ret = INF; 62     for (int i=MAXL-1; i>=0; i--) 63         if (dep[an[x][i]]>=ht) ret = min(ret, nimo[x][i]), x = an[x][i]; 64     return ret; 65 } 66  67 inline int lca(int x, int y){ 68     int ret = INF; 69     if (dep[x]^dep[y]) ret = dep[x]>dep[y] ? swim(x, dep[y]) : swim(y, dep[x]); 70     if (x==y) return ret; 71     for (int i=MAXL-1; i>=0; i--) 72         if (an[x][i]^an[y][i]) 73             ret = min(ret, min(nimo[x][i], nimo[y][i])), 74             x = an[x][i], y = an[y][i]; 75     return min(ret, min(nimo[x][0], nimo[y][0])); 76 } 77  78 int main(){ 79     memset(vis, false, sizeof(vis)); 80     memset(an, 0, sizeof(an)); 81  82     n = NextInt(), m = NextInt(); 83     for (int i=1; i<=n; i++) 84         f[i] = i; 85     for (int i=0; i<m; i++) 86         bd[i].v = NextInt(), bd[i].u = NextInt(), bd[i].d = NextInt(); 87      88     sort(bd, bd+m); 89     for (int i=0; i<m; i++) 90         if (find(bd[i].u)^find(bd[i].v)) Add(bd[i].u, bd[i].v, bd[i].d); 91     for (int i=1; i<=n; i++) 92         if (!vis[i]) dep[i] = 0, BuildTree(i), nimo[i][0] = INF, an[i][0] = i; 93  94     for (int i=1; i<MAXL; i++) 95         for (int j=1; j<=n; j++) 96             an[j][i] = an[an[j][i-1]][i-1], 97             nimo[j][i] = min(nimo[j][i-1], nimo[an[j][i-1]][i-1]); 98      99     int Q, a, b;100     scanf("%d", &Q);101     while (Q--)102         scanf("%d %d", &a, &b),103         printf("%d\n", find(a)==find(b) ? lca(a, b) : -1);104 }
truck.cpp

 

机模大赛:

  题解:模拟,ans = ∑max{0, a[i]-a[i-1]}

 1 #include <cstdio> 2  3 int num, h[100010]; 4  5 int max(int a,int b){ 6     return a>b ? a : b; 7 } 8  9 int main(){10     scanf("%d",&num);11     for (int i=0; i<num; i++)12         scanf("%d", &h[i]);13     14     long long ans = 0;15     for (int i=0; i<num; i++)16         ans += max(0, h[i]-h[i-1]);17     printf("%lld",ans);18 }
block.cpp

 

花匠:

  题解:贪心,缩点,把满足的连这的一群点缩为一个

 1 #include <cstdio> 2 const int MAXN = 1e6+10; 3  4 int n, Pri, cj, a[MAXN]; 5  6 int main(){ 7     scanf("%d", &n), Pri = 1, cj = 1221; 8     for (int i=0; i<n; i++) 9         scanf("%d", a+i);10     for (int i=1; i<n; i++){11         if (a[i]>a[i-1] && cj!=1) cj = 1, Pri ++;12         if (a[i]<a[i-1] && cj!=0) cj = 0, Pri ++;13     }14     printf("%d", Pri);15 }
flower.cpp