zoukankan      html  css  js  c++  java
  • 2019 牛客多校 第五场

    题目链接:https://ac.nowcoder.com/acm/contest/885#question 链接

    A:

      题意:签到

    B:

      题意:给出fn的递推关系式和n,求fn。n的范围10^(10^6)

      题解:转化成矩阵连乘,这个数据量10进制优化可以过。 

    #include <bits/stdc++.h>
    using namespace std; 
    typedef long long ll;
    
    const int MAXN=2e6+5;
    
    ll f0, f1, a, b, mod;
    char s[MAXN]; 
    
    struct Matrix{
        ll m[2][2]; 
    };
    
    Matrix Mul(Matrix a, Matrix b)
    {
        Matrix ans; 
        ans.m[0][0]=0; ans.m[0][1]=0; 
        ans.m[1][0]=0; ans.m[1][1]=0;
        for(int i=0; i<2; i++)
            for(int j=0; j<2; j++)
                for(int k=0; k<2; k++)
                    ans.m[i][j]=(ans.m[i][j]+a.m[i][k]*b.m[k][j])%mod; 
        return ans;
    }
    
    Matrix qpow(Matrix a, ll n)
    {
        Matrix ans; 
        ans.m[0][0]=1; ans.m[0][1]=0; 
        ans.m[1][0]=0; ans.m[1][1]=1; 
        while(n)
        {
            if(n&1)
                ans=Mul(ans, a);
            a=Mul(a, a); 
            n>>=1;
        }
        return ans;
    }
    
    int main()
    {
        cin>>f0>>f1>>a>>b; 
        cin>>s>>mod; 
        int len=strlen(s);
        Matrix ans, coe;
        ans.m[0][0]=1; ans.m[0][1]=0; 
        ans.m[1][0]=0; ans.m[1][1]=1; 
        coe.m[0][0]=a; coe.m[0][1]=b; 
        coe.m[1][0]=1; coe.m[1][1]=0; 
        for(int i=len-1; i>=0;  i--)
        {
            ans=Mul(ans, qpow(coe, s[i]-'0'));
            coe=qpow(coe, 10);
        }
        ll res=(ans.m[1][0]*f1+ans.m[1][1]*f0)%mod;
        cout<<res<<endl;
        return 0;
    }
    View Code

    C:(未解决)

      题意:给出fn的递推式,求fn=v时,n为多少。

      题解:不难化简得:

      

        不过如何求n就涉及到了BSGS算法,没搞懂,具体可参见:https://blog.csdn.net/ccsu_cat/article/details/98184813

    G:

      题意:给一个字符串t,一个字符串s,找出s中有多少个子序列大于字符串t

      题解:划分情况,当字串长度大于t的长度时:组合数学直接求。当长度相等时:dp【i】【j】表示s中长度为i的后缀中长度为j的子序列大于t中长度为j的后缀。

         此时,分s【n+1-i】和t【m+1-j】的大小关系进行讨论。注意当j的1的时候特别判定。   

         具体可参考:https://blog.csdn.net/qq_43857314/article/details/98212272

    #include <bits/stdc++.h>
    using namespace std; 
    typedef long long ll;
    
    const int MAXN=3e3+5; 
    const ll mod=998244353;
    
    ll dp[MAXN][MAXN], com[MAXN][MAXN]; 
    char s[MAXN], t[MAXN];
    int n, m;
    
    void make_com()
    {
        for(int i=0; i<MAXN; i++)
            com[i][i]=1, com[i][0]=1;
        for(int i=1; i<MAXN; i++)
            for(int j=1; j<MAXN; j++)
                com[i][j]=(com[i-1][j]+com[i-1][j-1])%mod;
    }
    
    int main()
    {    
        make_com();
        int T;
        for(cin>>T; T--; )
        {
            cin>>n>>m;
            cin>>s+1>>t+1;
                    
            //子序列的长度大于m时 
            ll ans1=0;
            for(int i=1; i<=n-m; i++)  //起点
            {
                if(s[i]=='0') continue;
                for(int j=m; j<=n-i; j++)
                    ans1=(ans1+com[n-i][j])%mod;    
            }
            
            //长度相等的时候
            for(int i=0; i<=n; i++)
                for(int j=0; j<=m; j++)
                    dp[i][j]=0;
            for(int i=1; i<=n; i++)
                for(int j=1; j<=i; j++)
                {
                    if(s[i]=='0') dp[i][j]=dp[i-1][j-1];
                    if(j==1)
                    {
                        if(s[n+1-i]>t[m+1-j]) dp[i][j]=(dp[i-1][j]+com[i-1][j-1])%mod;
                        else dp[i][j]=dp[i-1][j];
                    }
                    else if(s[n+1-i]>t[m+1-j]) dp[i][j]=(dp[i-1][j]+com[i-1][j-1])%mod;
                    else if(s[n+1-i]==t[m+1-j]) dp[i][j]=(dp[i-1][j]+dp[i-1][j-1])%mod;
                    else dp[i][j]=dp[i-1][j];
                } 
            cout<<(ans1+dp[n][m])%mod<<endl;
        }
        return 0;
    } 
    View Code

    H:

      题意:用前m个小写字母构造长度为n的字符串,有(m-1)*m/2个条件,条件是:给出去除字符c1和c2后形成的串,构造一个满足条件的原串,如果没有的话,输出-1

      题解:给出了去除某2个字符后的串,其实就是告诉了我们原串中部分字符的相对顺序,可以通过建图,在拓扑排序输出即可,顺序在后的是入度。(建图的时候错了很多次.)

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MAXN=1e6+5;
    char str[MAXN], s[MAXN];
    int n, m, len, all;
    int cnt[30]; 
    int in[MAXN];
    vector<int> edge[MAXN], v[30], ans; 
    
    void make_map()
    {
        int pre=-1;
        memset(cnt, 0, sizeof(cnt));
        for(int i=0; i<len; i++)
        {
            int id=str[i]-'a'+1;
            cnt[id]++;
            if(v[id].size()<cnt[id])
            {
                v[id].push_back(++all);
                s[all]=str[i];
            }
            if(pre!=-1)
            {
                edge[pre].push_back(v[id][cnt[id]-1]);
                in[v[id][cnt[id]-1]]++;
            }
            pre=v[id][cnt[id]-1];
        }
    }
    
    void topo()
    {
        queue<int> q;
        for(int i=1; i<=all; i++)
            if(in[i]==0) q.push(i);
        while(!q.empty())
        {
            int p=q.front(); q.pop();
            ans.push_back(p);
            for(int i=0; i<edge[p].size(); i++)
            {
                int y=edge[p][i];
                in[y]--;
                if(in[y]==0) q.push(y);    
            }
        }
    }
    
    int main()
    {
        cin>>n>>m; 
        m=(m-1)*m/2;
        while(m--)
        {
            cin>>str>>len;
            if(len) cin>>str;
            else continue;
            make_map();
        }
        topo();
        if(ans.size()==n) 
            for(int i=0; i<n; i++)
                printf("%c", s[ans[i]]);
        else 
            printf("-1");
        
        return 0;
    }
    View Code

    I:

      题意:给出一个坐标系中给出一个矩形,和三角形的三条边长,输出满足该三角形完全在矩形内时的三个点的坐标。

      题解:找出最长的边c (假设这里是c)靠在x轴上,一端点在(0, 0), 然后求另一端点如果c>x,则该边向上旋转,直到接触到wh这个矩阵的边,然后设该点为第二个端点。之后你知道了两个点,三条边,就可以求出第三个点。(额,完美的错误想法)

         因为最长的边不一定是这样的(暴力ac代码验证得来的),不过那个三角形大概长成那样,可以直接暴力匹配三角形的边长判断是否满足条件也就6种情况而已。

    #include <bits/stdc++.h>
    using namespace std;
     
    const double eps=1e-8;
      
    struct Cod{
        double x, y;
    }ans[5];
    double w, h, a, b, c;
     
    bool solve(double a, double b, double c, int x, int y, int z)
    {
        ans[x].x=0, ans[x].y=0;
        if(a<=w)
            ans[y].x=a, ans[y].y=0;
        else
            ans[y].x=w, ans[y].y=sqrt(a*a-w*w);
        double ang=acos((a*a+b*b-c*c)*1.0/(2.0*a*b))+atan(ans[y].y*1.0/ans[y].x);
        ans[z].x=b*cos(ang), ans[z].y=b*sin(ang);
         
        if(ans[z].x>-eps&&ans[z].x<w+eps && ans[z].y>-eps&&ans[z].y<h+eps)
        {
            for(int i=0; i<3; i++)
                printf("%.12f %.12f ", ans[i].x, ans[i].y);
            printf("
    ");
            return true;
        }
        return false;      
    }
     
    int main()
    {
        int T;
        for(cin>>T; T--; )
        {
            cin>>w>>h>>a>>b>>c;
            if(solve(a, b, c, 0, 1, 2)) ;
            else if(solve(a, c, b, 1, 0, 2)) ;
            else if(solve(b, a, c, 0, 2, 1)) ;
            else if(solve(b, c, a, 2, 0, 1)) ;
            else if(solve(c, a, b, 1, 2, 0)) ;
            else if(solve(c, b, a, 2, 1, 0)) ; 
    //      WA      
    //        if     (a>=b && a>=c && (solve(a, b, c, 0, 1, 2) || solve(a, c, b, 1, 0, 2))) ;
    //      else if(b>=a && b>=c && (solve(b, a, c, 0, 2, 1) || solve(b, c, a, 2, 0, 1))) ;
    //      else if(c>=a && c>=b && (solve(c, a, b, 1, 2, 0) || solve(c, b, a, 2, 1, 0))) ;   
        }  
        return 0;
    }
    View Code
  • 相关阅读:
    牛牛的揠苗助长(二分)
    树型DP简单入门
    Rational Ratio(一道思维题)
    Tima goes to Xentopia(条件最短路)
    中国剩余定理
    求解逆元的三种方法
    samba 基本配置及自定义控制
    vue之虚拟DOM、diff算法
    vue-cli3构建ts项目
    VMware+node+nginx+vue
  • 原文地址:https://www.cnblogs.com/Yokel062/p/11296185.html
Copyright © 2011-2022 走看看