zoukankan      html  css  js  c++  java
  • 【67测试20161116】【数论】【DP】【思维】

    第一题:

    LGTB 得到了一个序列,他想在这个序列中选择一个最长的连续子序列,使得这个子序列的最大公约数等于1。请告诉他他能得到的最大长度,如果没有这样的序列,输出-1.

    对于50% 的数据,1  <=n <= 1000
    对于100% 的数据,1  <=n <= 10^5 1 <= ai <= 10^9


    解:首先,读题。。这个序列的公约数,是公共约数,所以,只要这个序列中有两个数的最大公约数为1,那么无论这个序列有多长,只要符合这个条件,那么它们所有的最大公约数,为1。所以答案为-1,或者,n。。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define maxn 100005
     6 using namespace std;
     7 int n,v[maxn],f[maxn],ans;
     8 int gcd(int a,int b)
     9 {
    10     return b==0?a:gcd(b,a%b);
    11 }
    12 int main()
    13 {
    14     freopen("seq.in","r",stdin);
    15     freopen("seq.out","w",stdout);
    16     scanf("%d",&n);
    17     for (int i=1;i<=n;i++)
    18       scanf("%d",&v[i]);
    19     for (int i=2;i<=n;i++)
    20     {
    21         if (gcd(v[i],v[i-1])==1){
    22             printf("%d",n);
    23             return 0;
    24         }
    25     }
    26     if (n==1&&v[n]==1) printf("1");
    27     else printf("-1");
    28     return 0;
    29 }

    第二题:

    LGTB 新买了一张n * m 的矩(桌) 阵(子),他想给某些1 * 1 的小矩形染色,使得染色之后,原矩阵的每个n * n 的子矩阵中都包含恰好k 个被染色了的小矩形。他想知道有多少种染色方案能让他满足上述要求。因为答案可能很大,请输出方案数模1000000007 (10^9 + 7) 后的值.

    对于15% 的数据,1  <=n *m <= 20, n <= m
    对于40% 的数据,1  <=n <= 10, n <= m <= 1000
    对于100% 的数据,1 <= n <= 100, n <= m <= 10^18, 0 <= k<=  n^2


    解:  这道题,考试的时候没怎么仔细想。因为不知道为什么考试的时候根本没有心情思考,一直很浮躁,不在状态。

       首先,要先找到:对于每n列中的第 i 列中的被染色数等于第n+i 列的染色数。以下为证明:

     i (1,2,3,......)对应当前列有第 i 个矩阵经过  n=4,m=9

    1

    1,2 1,2,3 1,2,3,4 2,3,4,5 3,4,5,6 4,5,6 5,6 6

    每列的染色数

    a

    b c d a b c d a

        注意到,红色部分,都是染色为a,因为1矩阵染了a,那2,3,4,5矩阵也该染a个,6矩阵也该染a个,才满足所有矩阵染的数相等。

        所以我们可以直接只算n列为一块,就可以了。但是最后一块不一定为n列。

        那么用dp[i][j]表示n列中的第 i 列染 j 个的方案数。dp[i][j]=∑(dp[i-1][j-p]*C(n,p)^T[i])%P。T[i]表示 i 这一列(在n列中的位置)在m中重复了几次。如红色部分所在列,重复了3次,而剩下部分所在列只重复了2次,也就是“最后一块不一定为n列”的解释。对于所有第 i 列而言,j<=i*n&&j<=k,染 p (p=min(n,j)) 个有C(n,p)中组合,有T[i]个第 i 列,所以方案数相乘(乘法原理:这是T[i]列同时满足),而对于所有的p,是加法∑,(加法原理:有p中不同的填法并列)。

        注意 i, j,p都可以从0 开始。乘方用快速幂。

        还有T[i]不一定是一个数组,可以改为判断当前 i 列是否小于m%n,如果小于则T[i]=m/n+1,否则为m/n。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define maxn 105
     6 #define ll long long
     7 #define P 1000000007//打错了mod数 
     8 #ifdef WIN32
     9 #define AUTO "%I64d"
    10 #else 
    11 #define AUTO "%lld"
    12 #endif
    13 using namespace std;
    14 ll n,m,k;
    15 ll dp[maxn][maxn*maxn],c[2][maxn][maxn];//组合--i 中取 j -- 0: m/n,1:m/n+1 
    16 ll ksm(ll cur,ll ki)
    17 {
    18     ll t=1,tmp=cur,kk=ki;
    19     while (kk)
    20     {
    21         if (kk%2) t=(t*tmp)%P;
    22         kk>>=1;
    23         tmp=(tmp*tmp)%P;
    24     }
    25     return t;
    26 }
    27 void pre()
    28 {
    29     for (int i=0;i<=100;i++)
    30     {
    31         c[0][i][0]=c[0][i][i]=c[1][i][0]=c[1][i][i]=1;
    32         for(int j=1;j<i;j++)
    33           {
    34               c[0][i][j]=c[1][i][j]=c[0][i-1][j-1]+c[0][i-1][j];//***
    35               c[0][i][j]%=P;
    36           }
    37     }
    38     ll xi=m/n;
    39     for (int i=0;i<=100;i++)
    40       for (int j=0;j<=i;j++)//<=i
    41       {
    42           c[0][i][j]=ksm(c[0][i][j],xi);
    43           c[1][i][j]=ksm(c[1][i][j],xi+1);
    44       }
    45 }
    46 int main()
    47 {
    48     freopen("table.in","r",stdin);
    49     freopen("table.out","w",stdout);
    50     scanf(AUTO AUTO AUTO,&n,&m,&k);
    51     pre();
    52     int cur=(1<=m%n);// choose 0 or 1
    53     for (int i=0;i<=min(n,k);i++)//pre work ,from 0可以不选 
    54       dp[1][i]=c[cur][n][i];
    55     for (int i=2;i<=n;i++)
    56     {
    57         int cu=(i<=m%n);// >=i choose 1
    58         for (int j=0;j<=i*n&&j<=k;j++)//  from 0
    59           for (int t=0;t<=min(n,(ll)j);t++)//min(n,j) from 0
    60           {
    61           //    dp[i][j]+=(dp[i-1][j-t]*c[cu][n][t])%P;
    62               dp[i][j]=(dp[i][j]+(dp[i-1][j-t]*c[cu][n][t])%P)%P;//注意加法原理和乘法原理 
    63           }
    64     }
    65     printf(AUTO,dp[n][k]);
    66     return 0;
    67 }

    第三题:

    LGTB 最近迷上了正方形,现在他有n 个在二维平面上的点,请你告诉他在这些点中选4 个点能组成四条边都平行于坐标轴的正方形的方案数有多少

    对于10% 的数据,1 <= n<=  50
    对于30% 的数据,1  <=n <= 1000
    对于100% 的数据,1  <=n  <=10^5,0 <= xi, yi <= 10^5


    解:

      这套题怎么两道都是相似的。。然后我就写了一个大暴力。判断每个点向它的左下方找长度依次为:1,2,3,..min(xi,yi)的满不满足正方形。居然还得了50。。意料之外。

    50分代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 1005
    using namespace std;
    int n,ans;
    struct pp{
        int x,y;
    };
    pp v[maxn*maxn];
    bool mp[maxn][maxn];
    int main()
    {
        freopen("square.in","r",stdin);
        freopen("square.out","w",stdout);
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            v[i].x=a;v[i].y=b;
            mp[a][b]=true;
        }
        for (int i=1;i<=n;i++)
        {   
            int xi=v[i].x,yi=v[i].y;
            if (xi==0||yi==0) continue;
            int ma=min(xi,yi);
            for (int j=1;j<=ma;j++)
            if (mp[xi-j][yi]&&mp[xi][yi-j]&&mp[xi-j][yi-j]){
                ans++;
            }
        }
        printf("%d",ans);
        return 0;
    }

      还有两天。不准备写正解了,还不如我自己复习呢。


    ��--1-1-11

  • 相关阅读:
    pl/sql配置-本地不安装oracle-登录pl/sql
    js中查看js对象的属性
    eos中nui提交表单
    Window clearTimeout() 方法与setTimeout
    小程序---app.json文件的配置,全局的,对所有页面都适用
    css--加载中样式
    Vue+axios请求本地json
    vue中通过方法返回data中的对象是这个{__ob__: Observer},怎么处理 呢???
    解决 canvas 绘图在高清屏中的模糊问题
    总结:活动类开发必知必会
  • 原文地址:https://www.cnblogs.com/lx0319/p/6071217.html
Copyright © 2011-2022 走看看