zoukankan      html  css  js  c++  java
  • 7月5日测试

    问题 A: 重复字符串

    时间限制: 1 Sec  内存限制: 256 MB
    提交: 230  解决: 105
    [提交][状态][讨论版]

    题目描述

    给定两个字符串a和b,我们可以定义一些操作:a*b为将字符串a和字符串b连接起来,比如a= "aoe",b= "jkw",那么a*b= "aoejkw"。进一步,我们可以有指数操作,a^0= "", a^1=a, a^2=a*a, a^n=a*(a^(n-1))=a*a*…*a (n个a)

    现在给你一个字符串,你可以将它看成是a^n的形式,比如字符串"abababab",可以认为是"abab"^2, 也可以是"abababab"^1,还可以是"ab"^4。

    现在问题是,给定的字符串,我们想让它变成a^n中的n达到最大,那么这个n最大是多少?例如:"abababab"最大的n是4。

    输入

    第一行,一个整数m,表示有m个字符串。

    接下来m行每行输入一个只含小写字母的字符串。

    输出

    输出m行,对于每行输出相应字符串的最大n。

    样例输入

    3 abcde aaaaaa abababab

    样例输出

    1 6 4

    提示

    30% 的数据:字符串的长度≤1000 ;

    100%的数据:字符串的长度≤1000000 , m≤10字符串内只含小写字母 。

    var n,i,m,j,asdasd:longint;
    s:array[1..10]of ansistring;
    st:ansistring;
    function ok(i:longint):boolean;
     var j,x:longint;
    begin
     x:=1;
     for j:=1 to n do
      begin
       if st[j]<>st[x] then exit(false);
       inc(x); if x>i then x:=1;
      end;
     exit(true);
    end;
    begin
     readln(m);
     for i:=1 to m do readln(s[i]);
     for j:=1 to m do
      begin
       st:=s[j]; n:=length(st);
       for i:=1 to n do
        begin
         if (n mod i=0)and(ok(i)) then
          begin
               writeln(n div i); 
               break; 
          end;
        end;
       end;
    end.

    此题做法考场上想到了用暴力做(还A了),含义还不是很懂

    其实好像还能用KMP的next数组做(完全不会)

    var
    q,t,len,i,tot,k:longint;
    flag:boolean;
    f:array[0..2000011] of longint;
    s:ansistring;
    function find(i,k:longint):longint;
    begin
      if k=0 then exit(0);
      if s[i]=s[f[k]+1] then exit(f[k]+1)
                           else exit(find(i,f[k]));
    end;
    procedure debug();
    var i:longint;
    begin
        for i:=1 to len do
        write(f[i],'  ');
        writeln;
    end;
    begin
      readln(t);
      for q:=1 to t do
      begin
        readln(s);
        len:=length(s);
        fillchar(f,sizeof(f),0);
        for i:=2 to len do
        begin
          k:=i-1;
          while (s[i]<>s[f[k]+1])and(k<>0) do
          begin
            k:=f[k];
          end;
          if k=0 then f[i]:=0 else f[i]:=f[k]+1 ;
    
        end;
        tot:=f[len];
        if tot=0 then begin writeln('1'); continue; end;
        i:=tot+1;
        flag:=true;
        while i<=len do
        begin
          if s[(i-tot) mod tot]<>s[i] then begin flag:=false; break; end;
          i:=i+1;
        end;
        if flag then writeln(len div (len-tot))
             else writeln('1');
    
      end;
    end.

    B: Fibonacci进制

    时间限制: 1 Sec  内存限制: 256 MB
    提交: 300  解决: 62
    [提交][状态][讨论版]

    题目描述

    定义一种Fibonacci进制,可以将十进制数用Fibonacci数表示。Fibonacci进制中,每个位上的数值只有0或1,权值是Fibonacci数。令f0=f1=1,fi=fi-1+fi-2, N=an*fn+an-1*fn-1+…+a1*f1,写成N=anan-1..a2a1f。Fibonacci表示中,不能出现相邻的两个1。例如:自然数(十进制)表示为Fibonacci进制为1=1F,2=10F,3=100F,4=3+1=101F,5=1000F,6=5+1=1001F,7=5+2=1010F。

    现在,Bsny将所有自然数按照Fibonacci进制,依次输出在屏幕上,110100101100010011010……现在,Bsny想知道这个长串的前N个数字中,包含多少个1。

    输入

    第一行一个整数N,表示统计范围是自然数的Fibonacci
    表示的前N个数字

    输出

    一个数,前N个数字中1的个数。

    样例输入

    21

    样例输出

    10
    很好的题,我们可以先找归率.令fib[i]表示长度为i的数的个数,其实就是第i个斐波那契数(顺便表示一下斐波那契数本身),W[i]数组表示第i组数的中一的个数(这里有一个很重要的递推关系——W[i]=F[i]+W[i-2]就是第i位为0第i加一位必为1,所以脑补一下就是啦。WC[i]表示W[i]的前缀和。具体见代码注释。
    //finally modified by lhq;
    //add some note;
    #include<bits/stdc++.h>
    using namespace std;
    
    static long long F[90], W[90], WC[90], P, Q;
    
    long long fsum(int n, long long P) {    //加上n位数前P个数中"1"的个数;  
    //  fprintf(stderr, "%d %I64d
    ", n, P);
      if (!P) return 0;
      if (P == 1) return 1;
      assert (P > 0 && P < F[n]);
      if (P < F[n-1]) {    // F[i]表示n-1位数的个数;
        return fsum(n-1,P);
      } else {       //若这种情况,n-2位为0的所有数“1”的和可以看做所有n-1位数"1"的和,就是把n位的"1"右移一位;
        P -= F[n-1];
        return W[n-1]+P+fsum(n-2,P);   
        //剩下的n-2位为"1"的数有P-F[n-1]个,把最高位上的"1"加上就是n-2位数前P-F[n-1]个数中"1"的个数,递归调用;
      }
    }
    
    int fn (int r, int n, long long P) {    //加上n位数中第P个数前r位;分2种情况,最高位为0或1;
      if (r <= 0) return 0;
      return P < F[n+1] ? fn(r-1,n-1,P) : 1+fn(r-2,n-2,P-F[n+1]);
    }
    
    int main () {
      int n, i, r;
      freopen ("fib.in", "r", stdin);
      freopen ("fib.out", "w", stdout);
      F[1] = W[1] = WC[1] = 1;
      for (i = 2; i < 90; i++) {
        F[i] = F[i-1] + F[i-2]; //fib数列,1,1,开始,fib[i]同时表示i位数的个数;
        W[i] = F[i] + WC[i-2];//i位数的"1"的个数;
        WC[i] = W[i] + WC[i-1];//W数组的前缀和;
      }
      assert(scanf("%I64d",&P) == 1);
      n = 1;
      while (n * F[n] <= P) {
        P -= n*F[n];
        Q += W[n];
        n++;
      }
      //Q已经加上了完整位中的所有"1";
      r = P % n;
      P /= n;
      Q += fsum(n,P);
      //fprintf(stderr,"%d %d %I64d
    ",r,n,P+F[n+1]);
      Q += fn(r,n,P+F[n+1]);
      printf("%I64d
    ",Q);
      return 0;
    };

    顺便说一下assert,就是里面东东是错的话编译器会提醒你滴

    问题 C: 发奖金

    时间限制: 1 Sec  内存限制: 256 MB
    提交: 199  解决: 15
    [提交][状态][讨论版]

    题目描述

    Bsny最近公司运作不佳,本年度利润才m元,但员工的奖金还是要发的,公司有n个员工,怎么发奖金这个完全由老板Bsny自己决定。Bsny想要么把这m元全发了,激励一下员工,但具体怎么分配方案有很多。比如m=1, n=2, 那么可以员工1发1元,员工2发0元;也可以员工1发0元,员工2发1元,有两种方案。

    但其实,Bsny还是有点吝啬的,他想这m元不一定全部作为奖金,可以部分留给自己,这样的话,发奖金的方案数就更多了。还是以m=1, n=2为例子:

    方案1:员工1发1元,员工2发0元

    方案2:员工1发0元,员工2发1元

    方案3:员工1发0元,员工2发0元

    意味着老板Bsny发的奖金范围为[0, m]。

    好奇的Bsny想知道,给定n和m,他有多少种发奖金的方案?这个答案很大,所以再给定一个p,最终的答案取模p的余数.

    输入

    第一行三个整数n, m, p。

    输出

    仅一行,一个整数表示最终的答案取模p的余数。

    样例输入

    2 1 5

    样例输出

    3
    此题各种数学小模板凑,首先答案就不好搞——把n元钱分给m个人的方案数怎么求?(0<=n<=N)

    这里介绍两种方法,首先,我们把n元钱看成n个球,然后用m-1个挡板把它分成m份,所以总方案数是(n-1)C(m-1)(有n-1个空隙),但这样是不能有一块为0的情况的,所以我们将求加上m个以后每块中减去一个,就能有0的情况了。为(n+m-1)C(m-1)。

    然后这边有一个求和公式:sigma((n+m-1)C(m-1))0<=m<=M ===(n+m)C(m);——ZYD大佬说他不清楚,貌似具体数学上有

    然后算出了答案为sigma(n+m)C(m)然后将它转化成阶乘的形势取个模就行啦(超复杂

    贴标程

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    typedef long long LL;
    const int N = 100005;
    
    LL w[N];
    LL fac[N], inv[N];
    LL p[N], c[N], cntP, cnt, a0, a1, m0, m1, P, mo;
    int n, m, ID;
    
    LL power(LL x, LL y, LL M)
    {
        LL ans = 1;
        for (; y > 0; y >>= 1) {
            if (y & 1) {
                ans *= x;
                if (M != -1) ans %= M;
            }
            x *= x;
            if (M != -1) x %= M;
        }
        return ans;
    }
    
    LL calcfac(LL n)
    {
        if (n < p[ID]) return fac[n];
        LL seg = n / P, rem = n % P;
        LL ret = power(fac[P - 1], seg, P);
        ret = ret * fac[rem] % P;
        cnt += n / p[ID];
        ret = ret * calcfac(n / p[ID]) % P;
        return ret;
    }
    
    LL calcinv(LL n)
    {
        if (n < p[ID]) return inv[n];
        LL seg = n / P, rem = n % P;
        LL ret = power(inv[P - 1], seg, P);
        ret = ret * inv[rem] % P;
        cnt -= n / p[ID];
        ret = ret * calcinv(n / p[ID]) % P;
        return ret;
    }
    
    LL exgcd(LL a, LL b, LL &x, LL &y)
    {
        if (b == 0) {
            x = 1; y = 0;
            return a;
        } else {
            LL r = exgcd(b, a % b, y, x);
            y -= a / b * x;
            return r;
        }
    }
    
    LL getinv(LL i, LL P)
    {
        LL x, y;
        exgcd(i, P, x, y);
        x %= P;
        x += (x < 0) * P;
        return x;
    }
    
    LL solve()
    {
        P = power(p[ID], c[ID], -1);
        fac[0] = 1;
        for (int i = 1; i < P; ++i) {
            fac[i] = fac[i - 1];
            if (i % p[ID] != 0)
                fac[i] = fac[i] * i % P;
        }
        inv[0] = 1;
        for (int i = 1; i < P; ++i) {
            inv[i] = inv[i - 1];
            if (i % p[ID] != 0)
                inv[i] = inv[i] * getinv(i, P) % P;
        }
        cnt = 0;
        LL ret = calcfac(n);
        //cout << ret << " " << cnt << endl;
        for (int i = 1; i <= m; ++i) {
            ret = ret * calcinv(w[i]) % P;
            //cout << w[i] << " " << ret << " " << cnt << endl;
        }
        ret = ret * power(p[ID], cnt, P) % P;
        return ret;
    }
    
    void solve_equation(LL a, LL b, LL c, LL &k, LL &l)
    {
        exgcd(a, b, k, l);
        k *= c;
        k %= b;
        k += (k < 0) * b;
        return;
    }
    
    int main()
    {
        freopen("reword.in", "r", stdin);
        freopen("reword.out", "w", stdout);
        cin>>n>>m>>mo;
        for (int i = 2; i < 100000; ++i) if (mo % i == 0) {
            p[++cntP] = i;
            for (; mo % i == 0; mo /= i) ++c[cntP];
        }
        w[1]=n,w[2]=m;
        n=n+m;
        m=2;
        LL sw = 0;
        for (int i = 1; i <= m; ++i) sw += w[i];
        if (n - sw > 1) w[++m] = n - sw;
        for (int i = 1; i <= cntP; ++i) {
            ID = i;
            a1 = solve();
            m1 = power(p[i], c[i], -1);
            if (i == 1) {
                a0 = a1;
                m0 = m1;
            } else {
                LL k, l;
                solve_equation(m0, m1, a1 - a0, k, l);
                a0 = a0 + k * m0;
                m0 *= m1;
            }
        }
        printf("%d
    ", a0);
        return 0;
    }

     

     

  • 相关阅读:
    Anaconda+Tensorflow环境安装与配置
    计算机视觉(视频追踪检测分类、监控追踪)常用测试数据集
    迁移学习( Transfer Learning )
    matlab函数_连通区域
    GMM的EM算法实现
    对​O​p​e​n​C​V​直​方​图​的​数​据​结​构​C​v​H​i​s​t​o​g​r​a​m​的​理​解
    opencv基于混合高斯模型的图像分割
    LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
    视频测试序列(转)
    高职扩招,拿大专学历
  • 原文地址:https://www.cnblogs.com/dancer16/p/7134141.html
Copyright © 2011-2022 走看看