• NOIP模拟·20141105题解


    A、韩信点兵

       

        结论题+模板题,用到了中国剩余定理,维基百科上讲的就比较详细,这里就不再赘述了……

        对于这题,我们先利用中国剩余定理($x equiv sum{(a_i m_i (m_i^{-1} mod p_i))}\, mod (prod{p_i})$)找到当前人数的最小可行解$x_0$,(如果$x_0$已经超过了$N$,直接输出无解即可)这时不难证明,对于任何一个可行解,都有 $$x_i = x_0 + k imes prod{P_i},k in mathbb{N}$$

        我们的目标是找到不超过$N$的最大可行解x',那么答案就是$N - x'$。注意这里如果直接枚举$k$的话有一个测试点会超时(看起来我的数据规模还是挺良心的……只卡掉了10分)。正确的做法是先用$N$减去$x_0$,这时剩下的部分就是$N - x' + k imes prod{P_i},k in mathbb{N}$,那么我们只需用这个结果对$prod{P_i}$取余即可得到答案。

      

     1 #include <cstdio>
     2 #include <cctype>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <queue>
     6 #include <cmath>
     7 #include <iostream>
     8 
     9 
    10 typedef long long LL;
    11 using namespace std;
    12 inline int lowbit(int x){return x & -x;}
    13 int gcd(int a, int b){return (!a) ? b : gcd(b % a, b);}
    14 template<typename T>T exgcd(T a, T b, T &x, T &y){
    15     if(!a){x = 0, y = 1return b;}
    16     T d = exgcd(b % a, a, y, x);
    17     x -= (b/a) * y;
    18     return d;
    19 }
    20 /*=====================================*/
    21 inline LL inv(LL a, LL mod){
    22     LL x, y;
    23     if(exgcd(a, mod, x, y) != 1)return -1;
    24     return (x % mod + mod) % mod;
    25 }
    26 LL n, M = 1, N[11], e, S = 0;
    27 int P[11], a[11], m;
    28 
    29 inline void init(){
    30     cin >> n >> m;
    31     for(int i = 0;i < m;++i){
    32         cin >> P[i] >> a[i];
    33         M *= P[i];
    34     }
    35     for(int i = 0;i < m;++i){
    36         N[i] = M / P[i];
    37         e = N[i] * inv(N[i], P[i]) % M;
    38         S = (S + e * a[i]) % M;
    39     }
    40 }
    41 
    42 inline void work(){
    43     LL x, y;
    44     exgcd<LL>(1, M, x, y);
    45     x = ((x * S % M) + M ) % M;
    46     if(x > n){cout << -1 << endl;return;}
    47     cout << (n - x) % M << endl;
    48 }
    49 
    50 int main(){
    51     #if defined DEBUG
    52     freopen("test""r", stdin);
    53     #else
    54     freopen("HanXin.in""r", stdin);
    55     freopen("HanXin.out""w", stdout);
    56     #endif
    57     
    58     init();
    59     
    60     work();
    61     
    62     return 0;
    63 }
    中国剩余定理

    B、月考统计

        经典模型——差分约束系统。设第i位同学的分数为$x_i$,所有同学的最低分数为0. 则统计表中的每条息$i,j,a_{ij}$都可以形式化为 $$x_i - x_j le a_{ij}$$。

        对于这样一组不等式,我们可以抽象化出图论模型:每个同学都抽象为一个节点,再设一个起点0,表示所有同学的最低分数。对于每个不等式$x_i - x_j le a_{ij}$,我们都从点i到点j连一条权值为$-a_{ij}$的有向边,表示从起点到点j的最长路权和最少比起点到i的最长路权和大$-a_{ij}$(可以用最长路的三角形不等式证明)。对于这样的图,用spfa求出从起点到每个点的最长路权和就是答案。

     1 /*=============================================================================================================================*/
     2 /*======================================================Code by Asm.Def========================================================*/
     3 /*=============================================================================================================================*/
     4 #include <cstdio>
     5 #include <iostream>
     6 #include <algorithm>
     7 #include <cmath>
     8 #include <cctype>
     9 #include <memory.h>
    10 #include <vector>
    11 #include <set>
    12 #include <string>
    13 #include <cstring>
    14 #include <map>
    15 #include <queue>
    16 #include <deque>
    17 #include <stack>
    18 #include <ctime>
    19 #include <iterator>
    20 #include <functional>
    21 #include <cstdlib>
    22 using namespace std;
    23 /*===================================================================================*/
    24 #define forall(it,v) for(__typeof(v.begin()) it = v.begin();it < v.end();++it) 
    25 #define pb push_back
    26 #define REP(i,j,k) for(i = j;i <= k;++i)
    27 #define REPD(i,j,k) for(i = j;i >= k;--i)
    28 #define iter(v) v::iterator
    29 typedef long long LL;
    30 template<typename T> void getint(T &x){
    31     char c = getchar();
    32     while(!isdigit(c))c = getchar();
    33     x = c - '0';
    34     while(isdigit(c = getchar()))x = x * 10 + c - '0';
    35 }
    36 /*============================================================================================*/
    37 const int maxn = 2000 + 5;
    38 int N, M;
    39 struct edge{
    40     int to, w;
    41     edge(int T, int W):to(T), w(W){}
    42 };
    43 vector<edge> adj[maxn];
    44 
    45 queue<int> Q;
    46 bool inQ[maxn] = {0};
    47 int dis[maxn] = {0}, cnt[maxn] = {0};
    48 inline void init(){
    49     cin >> N >> M;
    50     int i, x, y, a;
    51     while(M--){
    52         cin >> x >> y >> a;
    53         adj[x].push_back(edge(y, -a));
    54     }
    55     for(i = 1;i <= N;++i)
    56         Q.push(i);inQ[i] = 1;cnt[i] = 1;
    57 }
    58 inline void work(){
    59     int i, t;
    60     iter(vector<edge>) it;
    61     while(!Q.empty()){
    62         t = Q.front();Q.pop();inQ[t] = 0;
    63         for(it = adj[t].begin();it != adj[t].end();++it)
    64             if(dis[t] + it->w > dis[it->to]){
    65                 dis[it->to] = dis[t] + it->w;
    66                 if(!inQ[it->to]){
    67                     if(cnt[it->to] == N){
    68                         cout << "SOMEONE LAY!" << endl;
    69                         return;
    70                     }
    71                     Q.push(it->to);inQ[it->to] = 1;++cnt[it->to];
    72                 }
    73             }
    74     }
    75     for(i = 1;i <= N;++i)
    76         cout << dis[i] << ' ';
    77 }
    78 
    79 int main(){
    80     #ifdef DEBUG
    81     freopen("test""r", stdin);
    82     #else
    83     freopen("ExamStat.in""r", stdin);
    84     freopen("ExamStat.out""w", stdout);
    85     #endif
    86     
    87     init();
    88     work();
    89     
    90     #ifdef DEBUG
    91     //cout << endl << (double)clock() / CLOCKS_PER_SEC <<endl;
    92     #endif
    93     return 0;
    94 }
    spfa解差分约束

     【C、神奇的压缩机

        神奇的压缩机,神奇的阅读题……

        这题改编自第21场Andrew Stankevich's Contest(俄国的ACM多校训练赛)的Lempel-Ziv Compression……

        当时我的解法是预处理出字符串中每个子串的“满足i小于子串长度且i前缀与i后缀相等的i”的最大值(或 原串的每个后缀的KMP-next数组)……听起来相当拗口,不过套用KMP的预处理过程可以降低思维难度。

     1 //Verdict: Accepted 2 
     2 // Submission Date: 2014-10-02 16:34:32
     3 // Time: 8256MS
     4 // Memory: 34624KB
     5 
     6 /*======================================================Code by Asm.Def========================================================*/
     7 #include <cstdio>
     8 #include <iostream>
     9 #include <algorithm>
    10 #include <cmath>
    11 #include <cctype>
    12 #include <memory.h>
    13 #include <cstring>
    14 #include <cstdlib>
    15 using namespace std;
    16 #define maxn ((int)4.1e3)
    17 
    18 typedef long long LL;
    19   
    20 char ch[maxn];
    21 int len = 0, minbit[maxn], *next[maxn];
    22 int l[maxn], r[maxn], str[maxn];
    23 
    24 
    25 inline void getnext(int l){
    26     int i, j, L = len - l;
    27     next[l] = new int[L+2];
    28     int *Next = next[l];
    29     Next[0] = 0;
    30     for(i = 1;i < L;++i){
    31         j = Next[i-1] - 1;
    32         while(ch[l+i] != ch[l+j+1] && j >= 0)
    33             j = Next[j] - 1;
    34         if(ch[l+i] == ch[l+j+1])
    35             Next[i] = j + 2;
    36         else Next[i] = 0;
    37     }
    38 }
    39 void printpro(int i){
    40     if(str[i] == i){
    41         if(r[i])printpro(r[i]-1);
    42         int j;
    43         for(j = r[i];j <= i;++j)putchar(ch[j]);
    44         return;
    45     }
    46     printpro(str[i]);
    47     printf("(%d,%d)", r[i], l[i]);
    48 }
    49 int main(){
    50     #ifdef DEBUG
    51     assert(freopen("test","r",stdin));
    52     #endif
    53 
    54     char c;
    55     while(isalpha(c = getchar()))str[len] = len, ch[len++] = c;
    56     int i, j, Min, t;
    57     for(i = 0;i < len - 1; ++i)
    58         getnext(i);
    59     minbit[0] = 9;
    60     for(i = 1;i < len; ++i){
    61         Min = 0x7fffffff;
    62         for(j = 0;j < i;++j)
    63             if(minbit[j] + (i-j)*9 < Min){
    64                 Min = minbit[j] + (i-j)*9;
    65                 str[i] = i;
    66                 r[i] = j+1;
    67             }
    68         for(j = 0;j < i; ++j){
    69             t = next[j][i-j];
    70             if(!t)continue;
    71             if(minbit[i-t] + 25 < Min){
    72                 Min = minbit[i-t] + 25;
    73                 str[i] = i-t;
    74                 r[i] = i+1-t-j;
    75                 l[i] = t;
    76             }
    77         }
    78         minbit[i] = Min;
    79     }
    80     printf("%d ", minbit[len-1]);
    81     printpro(len-1);
    82     return 0;
    83 }
    动态规划
  • 相关阅读:
    Mina入门demo
    MySQL数据库插入中文时出现Incorrect string value: 'xE6x97xB7xE5x85xA8' for column 'sz_name' at row 1
    synchronized和volatile
    springboot+Zookeeper+Dubbo入门
    zookeeper的安装
    windows下dubbo-admin的安装
    Java 枚举类
    Mysql 解压版 安装时候的注意事项
    Java——JDBC鶸笔记
    《初识Java微信公众号开发》 学习中遇到的困难
  • 原文地址:https://www.cnblogs.com/Asm-Definer/p/4076100.html
Copyright © 2020-2023  润新知