2019牛客暑期多校训练营(第五场)

 

B.generator 1(矩阵快速幂)

•题意

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

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

  求 fn%mod ;

•思路

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

  $\left( \begin{array}{cc} f_{i} \\ f_{i-1} \end{array}\right)=\left( \begin{array}{cc} a&b \\ 1&0 \end{array}\right)\cdot\left( \begin{array}{cc} f_{i-1} \\ f_{i-2} \end{array}\right)$

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

  那么,原式可化为 $A_{i}=T\cdot 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=\bigg(\Big(\big((3\times 10)+1\big)\times 10+9\Big)\times 10+4\bigg)$;

  在计算 $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

 

posted @ 2019-08-02 12:05  MMMinoz  阅读(183)  评论(0编辑  收藏  举报