zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第五场)

     

    B.generator 1(矩阵快速幂)

    •题意

    已知 $f_{i}=af_{i-1}+bf_{i-2}$;

      输入 f0,f1,a,b,n,mod;

      求 fn%mod ;

    •思路

    首先将递推式转化为矩阵乘法表达式:

      $left( egin{array}{cc} f_{i} \ f_{i-1} end{array} ight)=left( egin{array}{cc} a&b \ 1&0 end{array} ight)cdotleft( egin{array}{cc} f_{i-1} \ f_{i-2} end{array} ight)$

      不妨令 $mathbf{A_{i}} =left( egin{array}{cc} f_{i} \ f_{i-1} end{array} ight)$ , $mathbf{T} =left( egin{array}{cc} a&b \ 1&0 end{array} ight)$;

      那么,原式可化为 $A_{i}=Tcdot A_{i-1}=T^{2}cdot A_{i-2}= cdots = T^{i-1}cdot A_{1}$;

      还差最后一步,如何处理 $T^{n-1}$ ?

      n 很大很大很大;

      考虑到秦九韶算法,将 n 分解;

      假设 n-1 = 3194;

      那么 n 可分解为 $n=igg(Big(ig((3 imes 10)+1ig) imes 10+9Big) imes 10+4igg)$;

      在计算 $T^{3194}$ 时,可以按照字符串的位数进行处理;

      先计算 ans = T3;

      ans = ans10·T1;(ans=T31)

      ans = ans10·T9;(ans = T319)

      ans = ans10·T4;(ans = T3194)

    •代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 ll xx,yy,a,b;
     5 ll n,mod;
     6 char s[10000005];
     7 struct matrix
     8 {
     9     ll m[2][2];
    10     matrix()
    11     {
    12         memset(m,0,sizeof(m));
    13     }
    14     void Init()
    15     {
    16         for(int i=0;i<2;++i)
    17             m[i][i]=1;
    18     }
    19 };
    20  
    21 matrix mul(matrix a,matrix b)
    22 {
    23     matrix c;
    24     for(int i=0;i<2;i++)
    25         for(int j=0;j<2;j++)
    26             for(int k=0;k<2;k++)
    27                 c.m[i][j]=(c.m[i][j]+(a.m[i][k]*b.m[k][j])%mod)%mod;
    28     return c;
    29 }
    30  
    31  
    32 matrix qpow_matrix(matrix a,ll b)
    33 {
    34     matrix res;
    35     res.Init();
    36     while(b)
    37     {
    38         if(b&1)
    39             res=mul(res,a);
    40         a=mul(a,a);
    41         b>>=1;
    42     }
    43     return res;
    44 }
    45  
    46  
    47 int main()
    48 {
    49     cin>>xx>>yy>>a>>b>>s>>mod;
    50     matrix t,a1;
    51     t.m[0][0]=a,t.m[0][1]=b;
    52     t.m[1][0]=1,t.m[1][1]=0;
    53     a1.m[0][0]=yy,a1.m[0][1]=0;
    54     a1.m[1][0]=xx,a1.m[1][1]=0;
    55     int len=strlen(s);
    56  
    57     for(int i=len-1;i>=0;i--)
    58     {
    59         if(s[i]>'0')
    60         {
    61             s[i]--;
    62             for(int j=i+1;j<=len-1;j++)
    63                 s[j]='9';
    64             break;
    65         }
    66     }
    67  
    68     matrix ans,tt;
    69     ans.m[0][0]=1,ans.m[1][1]=1;
    70     for(int i=0;i<len;i++)
    71     {
    72         int num=s[i]-'0';
    73         ans=qpow_matrix(ans,10);
    74 //        cout<<"num:"<<num<<endl;
    75         if(num==0)
    76             continue;
    77         tt=qpow_matrix(t,num);
    78         ans=mul(ans,tt);
    79     }
    80     matrix an=mul(ans,a1);
    81     cout<<an.m[0][0]<<endl;
    82 }
    View Code

    H.subsequence 2(拓扑排序)

    •题意

    有一个长度为n的小写字母字符串,

    现给你m*(m-1)/2条信息

    每一条信息包含两个可以显示的字母

    接着根据顺序显示此字符串里的这两个字母

    问是否存在,如果存在输出

    •思路

    可以给每个字母标一个序号,

    根据字母的先后顺序连边建图

    例如

    abbcacbac

    9 3                标号                连边建图

    ab 6

    abbaba           分别标号为1 2 3 4 5 6         1->2,2->3,3->4,4->5,5->6

    ac 6

    acacac          其中c标号为7 8 9,因为a已经被标号     1->7,7->4,4->8,8->6,6->9

    bc 6

    bbccbc              bc都已经被标号           2->3,3->7,7->8,8->5,5->9

    然后利用拓扑排序看是否可以组成存在且唯一的序列

    •代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define ll long long
      4 const int maxn=1e5+5;
      5 queue<int> q;
      6 vector<int> v[maxn];
      7 vector<int> p[27]; //p[i]存第i字母的所有标号
      8 int Indu[maxn];//入度
      9 char s[maxn];
     10 int cnt=0;
     11 bool vis[27];
     12 int a[27];//a[i]=j即第i个字母的第j个标号
     13 map<int,char> mp;
     14 int n,m;
     15 
     16 bool topsort()
     17 {
     18     while(!q.empty())
     19         q.pop();
     20 
     21     int num=0;
     22     for(int i=1;i<=cnt;i++)
     23         if(!Indu[i])
     24             q.push(i);
     25             
     26     while(!q.empty())
     27     {
     28         int now=q.front();
     29         q.pop();
     30         num++;
     31         
     32         s[num]=mp[now];
     33         for(int i=0;i<v[now].size();i++)
     34         {
     35             if(--Indu[v[now][i]]==0)
     36                 q.push(v[now][i]);
     37         }
     38     }
     39     if(num==n)
     40         return true;
     41     else
     42         return false;
     43 }
     44 
     45 
     46 int main()
     47 {
     48     cin>>n>>m;
     49     for(int k=1;k<=m*(m-1)/2;k++)
     50     {
     51         char ch[2];
     52         int len;
     53         scanf("%s%d",ch,&len);
     54         if(len==0)
     55             continue;
     56         scanf("%s",s+1);
     57         for(int i=1;i<=len;i++)
     58         {
     59             int cur=s[i]-'a';
     60             if(vis[cur])//没标过号的才标号
     61                 continue;
     62             cnt++;
     63 
     64             p[cur].push_back(cnt);
     65             mp[cnt]=s[i];//标号与字母映射
     66         }
     67         
     68         vis[ch[0]-'a']=1;
     69         vis[ch[1]-'a']=1;
     70 
     71         a[ch[0]-'a']=0;//连边关系从头开始
     72         a[ch[1]-'a']=0;
     73 
     74         for(int i=1;i<len;i++)
     75         {
     76             int uu=s[i]-'a';
     77             int vv=s[i+1]-'a';
     78 
     79             if(a[uu]==p[uu].size())
     80             {
     81                 puts("-1");
     82                 return 0;
     83             }
     84             a[uu]++;
     85             if(a[vv]==p[vv].size())
     86             {
     87                 puts("-1");
     88                 return 0;
     89             }
     90             v[p[uu][a[uu]-1]].push_back(p[vv][a[vv]]);
     91             Indu[p[vv][a[vv]]]++;
     92         }
     93     }
     94     if(topsort())
     95     {
     96         for(int i=1;i<=n;i++)
     97             cout<<s[i];
     98     }
     99     else
    100     {
    101         puts("-1");
    102         return 0;
    103     }
    104 }
    View Code
  • 相关阅读:
    LeetCode OJ
    LeetCode OJ
    LeetCode OJ
    linux tips
    vim more
    vim basic
    cut
    paste
    uniq
    Linux的用户
  • 原文地址:https://www.cnblogs.com/MMMinoz/p/11287823.html
Copyright © 2011-2022 走看看