zoukankan      html  css  js  c++  java
  • SCAU RP Test —— 因式分解与组合

    D  RP Test

    Time Limit:1000MS  Memory Limit:65535K

    题型: 编程题   语言: 无限制

     

    描述

        LRC是SCAU_ACM校队的主席,职业生涯为校队作过很多贡献。除此之外,LRC也被各路ACMER奉为RP之神,源于以下两件事:
            1.曾用随机算法以1/(50^100)概率AC了一道dp题;
            2.省赛抽奖现场以1/600概率抽中特等奖获得一个4T的SSD。
        但大家不知道,LRC有一个测试当天RP值的奇葩方法。首先,用随机算法random出一个长度为n的数组a1,a2...,an;然后,再用随机算法random出一个长度为m的数组b1,b2...,bm;紧接着,依然是用随机算法random出一个正整数c;
    接下来,LRC可以得到一个n*m的矩阵F,使得矩阵中的每个元素Fij=ai*bj;最后,计算一下F有多少个子矩阵,它的各个元素之和被c整除,那么这个值,就是他的RP值。
        现在LRC将所有的数random出来了,他想让未来校队的大神,也就是你,计算一下他的RP值。
    

     

    输入格式

    第一行一个正整数T(T<=100),代表测试数据的组数。
    每组数据有3行。
    第一行三个正整数n,m,c
    第二行有n个正整数a1,a2...,an
    第三行有m个正整数b1,b2...,bm
    数据范围:
    1<=n,m<=100
    1<=ai,bi<=100
    1<=c<=1000
    

     

    输出格式

    每组数据输出一行。
    输出一个数,代表LRC的RP值。

     

    输入样例

    2
    2 3 5
    2 3
    1 3 4
    2 3 11
    2 3
    1 3 4
    
    

     

    输出样例

    6
    0
    

     

    Hint

    样例中,有两个数组生成的2x3矩阵F如下:
    2  6  8
    3  9  12
    
    元素和能被5整除的的子矩阵有6个,分别是
     
     
     
    题解:
    表格是有两个数组a,b的乘积构成的,要求找出能够被c整除的子矩阵个数。直接构造表格,然后枚举。这种做法肯定会超时的。
    那么要仔细分析,找突破点了:
    能够被c整除,即表明这个子矩阵是c的倍数。
    那么思路是:找出数组a每个区间和的因子x,v[x]++。然后枚举b数组每个区间和,对于每一个区间和s,求出s要成为c的倍数所缺少的因子,
    这个因子的个数——v[x],就是就是能与当前b数组区间构成是c倍数的子矩阵的a数组的子矩阵个数。(相当抽象)
     
     
    代码如下:
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    
    using namespace std;
    
    int a[110],b[110], v[100000];//数组v记录因子个数
    
    int gcd(int a,int b)
    {
        return b==0?a:gcd(b,a%b);
    }
    
    int main()
    {
        int n,m,c,s,T,r,k,ans;
        scanf("%d",&T);
        while(T--)
        {
            ans = 0;
            memset(v,0,sizeof(v));
            scanf("%d%d%d",&n,&m,&c);
            for(int i = 0; i<n; i++) scanf("%d",&a[i]);
            for(int i = 0; i<m; i++) scanf("%d",&b[i]);
    
            for(int i = 0; i<n; i++ )
            {
                s = 0;
                for(int j = i; j<n; j++)
                {
                    s += a[j];
                    k = sqrt(s);
                    for(int t = 1; t<=k; t++)//因子从1开始
                    {
                        if(s%t==0)//记录每个因子
                        {
                            v[t]++;
                            /*如果相等,则只需记录一个。每个不同的因子都代表着这个区间,在接下来与
                            b数组的区间结合(合法的话),如果重复记录同一个因子,会误认为有两个区间和
                            的因子都含有t*/
                            if(t!=s/t)
                                v[s/t]++;
                        }
                    }
                }
            }
    
            for(int i = 0; i<m; i++ )
            {
                s = 0;
                for(int j = i; j<m; j++)
                {
                    s += b[j];
                    //gcd(s,c)即s要成为c的倍数所缺少的因子
                    ans += v[c/gcd(s,c)];
                }
            }
            printf("%d
    ",ans);
        }
    }
    


     
     
  • 相关阅读:
    ADO.NET 中的数据并发
    net中前台javascript与后台c#函数相互调用
    js正则函数match、exec、test、search、replace、split使用介绍集合
    jQuery遍历Table tr td td中包含标签
    SQL你必须知道的-查询聚合分组排序
    haut-1280 诡异的迷宫
    int、long long等的取值范围
    codeforce 855B
    nyoj-2357
    codeforces 858A
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7538765.html
Copyright © 2011-2022 走看看