2019牛客多校第五场

digits

题意

给定一个n,要构造一个数,本身是n个倍数,每一位的数加起来也是n的倍数。

分析

输出n个n即可,显然可以整除得到1..0..1..0..1,而且无论每一位上的数是什么,个数都是n个倍数,因此和可以整除n。

代码

#include <bits/stdc++.h>
using namespace std;
int t,n;
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            printf("%d",n);
        }
        printf("
");
    }
    return 0;
}

B generator 1

题意

广义斐波那契数列求第n项。

分析

  • 使用矩阵快速幂加速递推,但是指数很大,无法变成二进制来进行快速幂,只能使用十进制的快速幂。
  • 十进制快速幂其实就是对于大指数来说,像普通的字符串转大数的过程模拟一遍即可,比如字符串转大数是t=t*10+s[i]-'0',在快速幂这里,因为是在指数位置,所以是先t=Pow(t,10),然后t=t*Mul(x,s[i]-'0'),即乘法变为幂运算,加法变为乘法。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+50;
char s[N];
ll mod;
struct Mat{
    ll a[2][2];
    void init(){
        memset(a,0,sizeof(a));
    }
    void print(){
        for(int i=0;i<2;i++){
            for(int j=0;j<2;j++){
                printf("%d ",a[i][j]);
            }
            printf("
");
        }
    }
};
Mat mul(Mat a,Mat b){
    Mat ans;
    ans.init();
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            for(int k=0;k<2;k++){
                ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
            }
        }
    }
    return ans;
}
Mat Pow(Mat a,ll n){
    Mat ans;
    ans.init();
    ans.a[0][0]=ans.a[1][1]=1;
    while(n){
        if(n%2){
            ans=mul(ans,a);
        }
        a=mul(a,a);
        n/=2;
    }
    return ans;
}
ll X0,X1,a,b;
int main(void){
    // freopen("in.txt","r",stdin);
    scanf("%lld%lld%lld%lld",&X0,&X1,&a,&b);
    scanf("%s%lld",s,&mod);
    Mat tr;
    tr.init();
    tr.a[0][1]=1;
    tr.a[1][0]=b;
    tr.a[1][1]=a;
    Mat ans;
    ans.init();
    ans.a[0][0]=1;
    ans.a[1][1]=1;
    int len=strlen(s);
    for(int i=0;i<len;i++){
        ans=Pow(ans,10ll);
        ans=mul(ans,Pow(tr,s[i]-'0'));
    }
    Mat b;
    b.init();
    b.a[0][0]=X0;
    b.a[1][0]=X1;
    ans=mul(ans,b);
    printf("%lld
",ans.a[0][0]);
    return 0;
}

H subsequence 2

题意

要构造一个长度为n的字符串,有m种字符,给出两两之间的关系,和该字符串只含这两个字符的形式。

分析

  • 要构造出字符串显然需要字符之间的位置关系,对于每个关系,我们将相邻的字符连一条有向边,拓扑排序即可。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+50;
int n,m,len;
char t[N],s[N];
struct Edge{
    int v,next;
}edge[N*20];
int k;
int cnt,head[N];
int ind[N],tp[N];
bool flag;
int pos[26][N],ac[26];
int num;
void init(){
    cnt=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v){
    edge[cnt]=Edge{v,head[u]};
    head[u]=cnt++;
    ind[v]++;
}
void topo(){
    queue<int> q;
    for(int i=1;i<=num;i++){
        if(!ind[i]){
            q.push(i);
            tp[k++]=i;
        }
    }
    int cnt=0;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        cnt++;
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            ind[v]--;
            if(!ind[v]){
                q.push(v);
                tp[k++]=v;
            }
        }
    }
    if(cnt!=num){
        flag=true;
    }
}
map<int,char> mp;
int main(void){
    // freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    init();
    memset(pos,-1,sizeof(pos));
    for(int i=0;i<m*(m-1)/2;i++){
        scanf("%s",t);
        scanf("%d",&len);
        if(!len){
            continue;
        }
        scanf("%s",s);
        memset(ac,0,sizeof(ac));
        int idx=s[0]-'a';
        ac[idx]++;
        if(pos[idx][ac[idx]]==-1){
            pos[idx][ac[idx]]=++num;
        }
        int p=pos[idx][ac[idx]];
        mp[p]=s[0];
        for(int j=1;j<len;j++){
            int idx=s[j]-'a';
            ac[idx]++;
            if(pos[idx][ac[idx]]==-1){
                pos[idx][ac[idx]]=++num;
            }
            int tt=pos[idx][ac[idx]];
            mp[tt]=s[j];
            add(p,tt);
            p=tt;
        }
    }
    topo();
    if(flag || k!=n){
        printf("-1
");
    }else{
        for(int i=0;i<k;i++){
            printf("%c",mp[tp[i]]);
        }
        printf("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zxcoder/p/11326817.html