zoukankan      html  css  js  c++  java
  • 银联高校极客挑战赛 初赛 第二场

    开场几十分钟后才开始打的,实验室居然锁门了。。。

    A. 码队GO

    左上、右下角为(1,1)、(x,y)的矩阵的大小,dp处理

    然后一个裸的二分答案

    (1,1) (x,y) (x-k,y-k) 三个点

    sum=

    update:

    题解说O(Tn^3)就是不严谨了。

    20*300^3=540000000

    这样都说能过!!!

    如此接近1秒可以跑的数据量,

    有时要考虑常数的大小,是否没跑满的情况!然而没有提及。

    我的第二个代码:

    n^2+(n-1)^2+...+1^1 = 1/6 * n*(n+1)*(2n+1)

    相当于/3,实际是180901000,已经是极为接近了。

    估计有些n^3的写法,也有这样的时间复杂度可以除以一个系数的情况。

    而实际上呢,

    有数据可以让它跑满吗?

    可以的,如

    然而出题人有这种闲情逸致弄这样的极限数据吗?

    我不认为。。。

    就像有些邀请赛,如2019南昌邀请赛。。。

    (然而经过常数优化后,633ms过了)

    搞个快读,多交几次,估计就能过去了。

    有时也要考虑一下这种类型的情况。。。

    另外一个更巧妙的O(n^3)防被卡方法:

    右下端点按照可以制造的最大矩阵的大小,从大到小进行处理

    避免全为'*'和全为'.'两个极端数据的卡

    几十ms

     code1:

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <iostream>
     8 using namespace std;
     9 #define ll long long
    10 
    11 const double eps=1e-8;
    12 const ll inf=1e9;
    13 const ll mod=1e9+7;
    14 const int maxn=3e2+10;
    15 
    16 char str[maxn][maxn];
    17 int f[maxn][maxn];
    18 
    19 int main()
    20 {
    21     int t,n,m,l,r,mid,i,j;
    22     bool vis;
    23     scanf("%d",&t);
    24     while (t--)
    25     {
    26         scanf("%d%d",&n,&m);
    27         for (i=1;i<=n;i++)
    28             scanf("%s",str[i]+1);
    29 
    30         for (i=1;i<=n;i++)
    31             for (j=1;j<=m;j++)
    32                 f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+(str[i][j]=='.');
    33 
    34         l=1,r=min(n,m);
    35         while (l<=r)
    36         {
    37             mid=(l+r)>>1;
    38             vis=0;
    39 
    40             for (i=mid;i<=n;i++)
    41                 for (j=mid;j<=m;j++)
    42                     if (f[i][j]-f[i-mid][j]-f[i][j-mid]+f[i-mid][j-mid]==mid*mid)
    43                         vis=1;  ///写成函数形成,遇到则退出true,这样会快一点;但是写起来不方便
    44             if (vis)
    45                 l=mid+1;
    46             else
    47                 r=mid-1;
    48         }
    49         printf("%d
    ",r*r);
    50     }
    51     return 0;
    52 }

     code2:

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <iostream>
     8 using namespace std;
     9 #define ll long long
    10 
    11 const double eps=1e-8;
    12 const ll inf=1e9;
    13 const ll mod=1e9+7;
    14 const int maxn=3e2+10;
    15 
    16 char str[maxn][maxn];
    17 int f[maxn][maxn];
    18 
    19 int main()
    20 {
    21     int t,n,m,i,j,k,l,r,g;
    22     scanf("%d",&t);
    23     while (t--)
    24     {
    25         scanf("%d%d",&n,&m);
    26         for (i=1;i<=n;i++)
    27             scanf("%s",str[i]+1);
    28 
    29         for (i=1;i<=n;i++)
    30             for (j=1;j<=m;j++)
    31                 f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+(str[i][j]=='.');
    32 
    33         /**
    34         避免全为'*'和全为'.'两个极端数据的卡
    35         **/
    36 
    37         r=0;
    38         ///from large to small
    39         for (i=n+m;i>r;i--)
    40         {
    41             for (j=max(1,i-m);j<=n;j++)
    42             {
    43                 k=i-j;
    44                 g=min(j,k);
    45                 for (l=r+1;l<=g;l++)    ///r+1来自乐逍大佬提醒
    46                     if (f[j][k]-f[j-l][k]-f[j][k-l]+f[j-l][k-l]!=l*l)
    47                         break;
    48                 if (l!=r+1)
    49                     r=l-1;
    50             }
    51         }
    52         printf("%d
    ",r*r);
    53     }
    54     return 0;
    55 }
    56 /*
    57 1
    58 2 3
    59 ...
    60 .**
    61 
    62 3 4
    63 ****
    64 ****
    65 ****
    66 
    67 3 4
    68 ....
    69 ....
    70 ....
    71 
    72 4 4
    73 ....
    74 ....
    75 ....
    76 ....
    77 */

    B. 码队弟弟的求和问题

    n,m为独立的两部分,相乘即可

    接下来是整除分块,对于同一块,余数是一个等差数列

    update:

    我只是找到了规律,

    应该培养推公式的能力。。。

    n%i 的数学式子

    gcd 的数学式子

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=1e9+7;
     14 const int maxn=1e5+10;
     15 
     16 ///sum(sum(i*j*(n mod i)(m mod j)) mod 1e9+7
     17 ///1e9
     18 
     19 int maxv=1e5;
     20 
     21 //int zhi[maxn];
     22 bool vis[maxn];
     23 
     24 ll work(ll n)
     25 {
     26     ll l,r,sum=0,a0,b0,q,g,xx,yy,zz;
     27     for (l=1;l<=n;l=r+1)
     28     {
     29         r=n/(n/l);
     30         if (l==r)
     31             sum+=n%l*l;
     32         else
     33         {
     34             ///a0=l,b0,q,g
     35             a0=l;
     36             b0=n%l;
     37             q=n/l;
     38             g=r-l+1;
     39 
     40             ///0^2+1^2+...
     41             (sum+=a0*b0%mod*g)%=mod;
     42             if (g&1)
     43                 (sum+=b0*g%mod*((g-1)/2))%=mod;
     44             else
     45                 (sum+=b0*(g/2)%mod*(g-1))%=mod;
     46             if (g&1)
     47                 (sum-=a0*q%mod*g%mod*((g-1)/2))%=mod;
     48             else
     49                 (sum-=a0*q%mod*(g/2)%mod*(g-1))%=mod;
     50 
     51             xx=g-1;
     52             yy=g;
     53             zz=2*g-1;
     54             if (xx%2==0)
     55                 xx/=2;
     56             else if (yy%2==0)
     57                 yy/=2;
     58             else
     59                 zz/=2;
     60             if (xx%3==0)
     61                 xx/=3;
     62             else if (yy%3==0)
     63                 yy/=3;
     64             else
     65                 zz/=3;
     66             (sum-=q*xx%mod*yy%mod*zz)%=mod;
     67 //                q*(g-1)*g*(2*g-1)/6
     68             ///sum+=a0*b0*g + b0*g*(g-1)/2 - a0*q*g*(g-1)/2 - q*(g-1)*g*(2*g-1)/6;
     69 
     70 //            sum+=a0*g-q*g*(g-1)/2;
     71         }
     72 //        printf("%lld %lld
    ",l,r);
     73     }
     74     return sum;
     75 }
     76 
     77 int main()
     78 {
     79     /*
     80     ///n 最小的质因数
     81     for (i=2;i<=maxv;i++)
     82     {
     83         if (!vis[i])
     84         {
     85             zhi[++cnt_zhi]=i;
     86             for (j)
     87         }
     88     }
     89     */
     90 
     91     ll n,m,i;
     92     ///two parts
     93     scanf("%lld%lld",&n,&m);
     94     printf("%lld",(work(n)*work(m)%mod+mod)%mod);
     95     return 0;
     96 }
     97 /*
     98 1 1
     99 2 2
    100 3 3
    101 4 4
    102 5 5
    103 6 6
    104 7 7
    105 1000000000 1000000000
    106 */

    C. 异世界幻想

    菜鸡不会推公式,只能找规律

    打表

    看这:

    http://blog.csdn.net/morejarphone/article/details/50677172

    https://www.cnblogs.com/dirge/p/5503289.html

    无根树 & prufer

    n^(n-2)

    update:

    我觉得没多少人能按照题解的方法写出来。。。

    我感觉更多的是xxx,甚至是yyy。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <iostream>
     8 using namespace std;
     9 #define ll long long
    10 #include <set>
    11 
    12 const double eps=1e-8;
    13 const ll inf=1e9;
    14 const ll mod=1e9+7;
    15 const int maxn=15;
    16 
    17 int n,a[maxn],hap[maxn],link[maxn],siz_n;
    18 ll sum=0;
    19 set<int>se;
    20 
    21 void judge(int step)
    22 {
    23     int x,y;
    24     if (step==n-1)
    25     {
    26         x=*se.begin();
    27         se.erase(se.begin());
    28         y=*se.begin();
    29         se.erase(se.begin());
    30         link[x]++,link[y]++;
    31         for (x=1;x<=n;x++)
    32             if (link[x]==1)
    33                 sum++;
    34         return;
    35     }
    36     x=*se.begin();
    37     se.erase(se.begin());
    38     y=a[step];
    39     link[x]++,link[y]++;
    40     hap[y]--;
    41     if (hap[y]==0)
    42         se.insert(y);
    43     judge(step+1);
    44 }
    45 
    46 void work(int step)
    47 {
    48     int i;
    49     if (step==n-1)
    50     {
    51         se.clear();
    52         memset(hap,0,siz_n);
    53         memset(link,0,siz_n);
    54         for (i=1;i<=n;i++)
    55             hap[a[i]]++;
    56         for (i=1;i<=n;i++)
    57             if (hap[i]==0)
    58                 se.insert(i);
    59         judge(1);
    60         return;
    61     }
    62     for (i=1;i<=n;i++)
    63     {
    64         a[step]=i;
    65         work(step+1);
    66     }
    67 }
    68 
    69 int main()
    70 {
    71     for (n=2;n<=10;n++)
    72     {
    73         siz_n=4*(n+1);
    74         sum=0;
    75         work(1);
    76         printf("n=%d sum=%lld
    ",n,sum);
    77     }
    78     return 0;
    79 }
    80 /*
    81 n=2 sum=2
    82 n=3 sum=6
    83 n=4 sum=36
    84 n=5 sum=320
    85 n=6 sum=3750
    86 n=7 sum=54432
    87 n=8 sum=941192
    88 n=9 sum=18874368
    89 
    90 n * (n-1)^(n-2)
    91 */

    代码

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <iostream>
     8 using namespace std;
     9 #define ll long long
    10 
    11 const double eps=1e-8;
    12 const ll inf=1e9;
    13 const ll mod=998244353;
    14 const int maxn=1e5+10;
    15 
    16 ll mul(ll a,ll b)
    17 {
    18     ll y=1;
    19     while (b)
    20     {
    21         if (b&1)
    22             y=y*a%mod;
    23         a=a*a%mod;
    24         b>>=1;
    25     }
    26     return y;
    27 }
    28 
    29 int main()
    30 {
    31     ll n;
    32     scanf("%lld",&n);
    33     if (n==1)
    34     {
    35         printf("1");
    36         return 0;
    37     }
    38 
    39     printf("%lld",n*mul(n-1,n-2)%mod);
    40     return 0;
    41 }
    42 /*
    43 n=2 sum=2
    44 n=3 sum=6
    45 n=4 sum=36
    46 n=5 sum=320
    47 n=6 sum=3750
    48 n=7 sum=54432
    49 n=8 sum=941192
    50 n=9 sum=18874368
    51 
    52 n * (n-1)^(n-2)
    53 */

    来自群里的大佬解答

    证明:

    1.不同的 大小为n-1的两个无根树,加上一个无根树后,还是无根树。

    2.在一个无根树的两个不同的点,加上这个点,唯一与这个点相连的点的度数加一,与其它无根树不一样了。

    引用另外的大佬一句总结

  • 相关阅读:
    养成好习惯:在控制面板里停止服务
    很吊炸天的Xcode插件,你想要的这都有
    Cscope how to support java and c++
    java_lambda表达式
    【C语言】14-返回指针的函数与指向函数的指针
    李洪强
    【C语言】13-指针和字符串
    李洪强-C语言7-C语言运算符
    【C语言】12-指向一维数组元素的指针
    李洪强-C语言6-控制结构
  • 原文地址:https://www.cnblogs.com/cmyg/p/11221780.html
Copyright © 2011-2022 走看看