首页 > 代码库 > 寒假训练4解题报告

寒假训练4解题报告

1.        Cosmic Tables

数据量比较大,这里不能直接暴力,用行指针和列指针表示当前行列是原来的第几行第几列

技术分享
#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int N = 1005;int n ,m , k , row[N] , col[N] , a[N][N];char s[5] ;int p1 , p2;int main(){  //  freopen("a.in" , "r" , stdin);    while(scanf("%d%d%d" , &n , &m , &k) == 3)    {        for(int i=1 ; i<=n ; i++)            for(int j =1 ; j<=m ; j++)                scanf("%d" , &a[i][j]);        int maxn = max(n , m);        for(int i=1; i<=maxn ; i++)            row[i] = i , col[i] = i;        for(int i=1 ; i<=k ; i++){            scanf("%s%d%d" , s , &p1 , &p2);            if(s[0] == g) printf("%d\n" , a[row[p1]][col[p2]]);            else if(s[0] == c){                int t = col[p1];                col[p1] = col[p2] , col[p2] = t;            }            else{                int t = row[p1];                row[p1] = row[p2] , row[p2] = t;            }        }    }    return 0;}
View Code

2.    Reducing Fractions

先打表记录10^7内的所有素因子

题目比较简单,但过程写的有点长,记录a数组中总共包含了多少的素因子,并记录其个数

然后根据这个个数不断将b[]中的元素消去以最大可能消去这些因子,但不超过a[]中所记录的因子数,并记录消去的因子数,说明这些数目的因子在a[]中也存在这么多

然后再返回将a[]中的元素也消去这么多因子

技术分享
  1 #include <cstdio>  2 #include <cstring>  3 #include <iostream>  4 #include <cmath>  5 using namespace std;  6 const int N = 100005;  7 const int maxn = 10000000;  8 int a[N] , b[N];  9 bool vis[maxn]; 10 int prime[maxn/10] , k , cnt[maxn/10] , del[maxn/10]; 11  12 void get_prime() 13 { 14     k=0; 15     memset(vis , 0 , sizeof(vis)); 16     for(int i=2 ; i<maxn ; i++){ 17         if(!vis[i]){ 18             prime[k++] = i; 19             for(int j=i+i ; j<maxn ; j+=i) vis[j] = true; 20         } 21     } 22 } 23  24 int bin_seach(int x) 25 { 26     int l=0 , r = k-1; 27     while(l<=r){ 28         int m = (l+r)>>1; 29         if(prime[m] == x) return m; 30         else if(prime[m] > x) r = m-1; 31         else l=m+1; 32     } 33 } 34  35 void get_factor(int x) 36 { 37     int t = (int)sqrt(x+0.5); 38     for(int i=0 ; i<k ; i++){ 39         if(prime[i]*prime[i] > x) break; 40         if(x % prime[i] == 0){ 41             while(x % prime[i] == 0) 42             { 43                 x /= prime[i]; 44                 cnt[i]++; 45             } 46         } 47     } 48     if(x>1) cnt[bin_seach(x)]++; 49 } 50  51 int del_factor(int x) 52 { 53     int m = x; 54     int t = (int)sqrt(x+0.5); 55     for(int i=0 ; i<k ; i++){ 56         if(prime[i]*prime[i] > x) break; 57         if(x % prime[i] == 0){ 58             while(x % prime[i] == 0) 59             { 60                 if(cnt[i]) m/=prime[i] , cnt[i]--,del[i]++; 61                 x /= prime[i]; 62             } 63         } 64     } 65     if(x>1){ 66         int pos = bin_seach(x); 67         if(cnt[pos]) m/=prime[pos] , cnt[pos]--,del[pos]++; 68     } 69     return m; 70 } 71  72 int get_a(int x) 73 { 74     int m = x; 75     int t = (int)sqrt(x+0.5); 76     for(int i=0 ; i<k ; i++){ 77         if(prime[i]*prime[i] > x) break; 78         if(x % prime[i] == 0){ 79             while(x % prime[i] == 0) 80             { 81                 if(del[i]) m/=prime[i] ,del[i]--; 82                 x /= prime[i]; 83             } 84         } 85     } 86     if(x>1){ 87         int pos = bin_seach(x); 88         if(del[pos]) m/=prime[pos] , del[pos]--; 89     } 90     return m; 91 } 92  93 int main() 94 { 95    // freopen("a.in" , "r" , stdin); 96     get_prime(); 97     int n,m; 98     while(scanf("%d%d" , &n , &m) == 2) 99     {100         memset(cnt , 0 , sizeof(cnt));101         for(int i=0 ; i<n ; i++)102         {103             scanf("%d" , a+i);104             get_factor(a[i]);105         }106         memset(del , 0 , sizeof(del));107         for(int i=0 ; i<m ; i++)108         {109             scanf("%d" , b+i);110             int tmp = b[i];111             b[i] = del_factor(tmp);112         }113 114         for(int i=0 ; i<n ; i++)115         {116             int tmp = a[i];117             a[i] = get_a(tmp);118         }119         printf("%d %d\n" , n , m);120         for(int i=0 ; i<n ; i++){121             if(i == 0) printf("%d" , a[i]);122             else printf(" %d" , a[i]);123         }124         puts("");125         for(int i=0 ; i<m ; i++){126             if(i == 0) printf("%d" , b[i]);127             else printf(" %d" , b[i]);128         }129         puts("");130     }131     return 0;132 }
View Code

3.     Olympiad

一道简单的贪心,最好情况必然为第一名,最差情况,可以先排序,a[] 由小到大, b[]由大到小,每次取尽可能多的成立的组,然后让其作为所有组的最后一名即可

技术分享
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int N = 100005;int a[N] , b[N] , sum[N] , vis[N];bool cmp(int a , int b){    return a>b;}int main(){   // freopen("a.in" , "r" , stdin);    int n , k;    while(scanf("%d%d" , &n , &k) == 2)    {        for(int i=0 ; i<n ; i++)            scanf("%d", a+i);        sort(a , a+n);        for(int i=0 ; i<n ; i++)            scanf("%d", b+i);        sort(b , b+n , cmp);        memset(vis , 0 , sizeof(vis));        int ans=0 , flag = 0;        int index = 0 ;        for(int i=0 ; i<n ; i++)        {            while(b[i]+a[index]<k || vis[index]){                if(index == n-1){flag = 1 ;break;}                index  = (index+1)%n;            }            if(flag) break;            vis[index]=1;            ans++;            index = (index+1)%n;        }        printf("%d %d\n" , 1 , ans);    }    return 0;}
View Code

4. Good Substrings

用字典树记录已存在的字符串,但不要傻傻的添加字符串时都从root开始,因为我们都是从某一点出发,每次往后多添加一个字符,所以第一层循环中可以每次都保留当前访问到的字典树的位置,从这个位置向下一格就好,否则会超时

技术分享
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int N = 1600;char s1[N] , s2[N];int sum[N] , k;bool good[N];struct Node{    Node *next[26];    int flag;    Node(){        flag = 0;        for(int i=0 ; i<26 ; i++)            next[i] = NULL;    }};Node *root;Node *cur;void add_string(int i , int &ans){    int id = s1[i]-a;    if(cur->next[id] == NULL) cur->next[id] = new Node();    cur = cur->next[id];    if(cur->flag == 0)        ans++;    cur->flag = 1;}int main(){   // freopen("a.in" , "r" , stdin);    int  k;    while(scanf("%s" , s1+1) == 1)    {        scanf("%s%d" , s2 , &k);        for(int i=0 ; i<26 ; i++)            good[i] = s2[i] == 1;        int len = strlen(s1+1);        for(int i=1 ; i<=len ; i++){            sum[i] = sum[i-1];            if(!good[s1[i]-a]) sum[i]++;        }        root = new Node();        int ans = 0;        for(int l=1 ; l<=len ; l++){            cur = root;            for(int r=l ; r<=len ; r++){                if(sum[r] - sum[l-1] <= k) add_string(r,ans);            }        }        printf("%d\n" , ans);    }    return 0;}
View Code

5.  Decoding Genome

一道dp题目,开始想到了要dp,不过一看n的取值就放弃dp了,不得不说自己很傻

当n值很大总应想到logn解决问题的矩阵快速幂

dp[i][c] 表示前 i 个字符,以 字符c结尾的种数 , 这里 c 有 m 种,所以用 m*m的矩阵进行快速幂即可

技术分享
#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define ll long longconst int N = 1<<6;const int MOD = 1000000007;int dp[30],m,k;ll n;char s[4];struct Matrix{    ll mat[52][52];    Matrix operator*(const Matrix &p)const{        Matrix ans;        for(int i=0 ; i<m ; i++){            for(int j=0 ; j<m ; j++){                ans.mat[i][j] = 0;                for(int k=0 ; k<m ; k++){                    ans.mat[i][j] += mat[i][k]*p.mat[k][j];                    ans.mat[i][j] %= MOD;                }            }        }        return ans;    }    void print()    {        for(int i=0 ; i<m ; i++){            for(int j=0 ; j<m ; j++)                cout<<mat[i][j]<<" ";            cout<<endl;        }    }};Matrix qpow(ll cnt , Matrix p){    Matrix ans;    for(int i=0 ; i<m ; i++)        for(int j=0 ; j<m ; j++)            if(i == j) ans.mat[i][j] = 1;            else ans.mat[i][j] = 0;    while(cnt){        if(cnt&1) ans = ans*p;        p = p*p;        cnt/=2;    }    return ans;}int char_to_int(char c){    if(c>=a&&c<=z) return c-a;    else return 26+(int)(c-A);}int main(){  //  freopen("a.in" , "r" , stdin);    while(scanf("%I64d%d%d" , &n , &m , &k) == 3)    {        Matrix p ;        for(int i=0 ; i<m ; i++)            for(int j=0 ; j<m ; j++) p.mat[i][j] = 1;        for(int i=0;i<m;i++) dp[i]=1;        for(int i=0 ; i<k ; i++)        {            scanf("%s" , s);            int g = char_to_int(s[0]);            int h = char_to_int(s[1]);            p.mat[g][h] = 0;        }        Matrix final = qpow(n-1 , p);        ll ans = 0;        for(int i=0 ; i<m ; i++)            for(int j=0 ; j<m ; j++){                ans += dp[i]*final.mat[j][i];                ans %= MOD;            }        printf("%I64d\n" , ans);    }    return 0;}
View Code

 

寒假训练4解题报告