博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
银联高校极客挑战赛 初赛 第二场
阅读量:4662 次
发布时间:2019-06-09

本文共 6890 字,大约阅读时间需要 22 分钟。

 

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

 

左上、右下角为(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 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 using namespace std; 9 #define ll long long10 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 else47 r=mid-1;48 }49 printf("%d\n",r*r);50 }51 return 0;52 }

 

 code2:

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 using namespace std; 9 #define ll long long10 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 small39 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\n",r*r);53 }54 return 0;55 }56 /*57 158 2 359 ...60 .**61 62 3 463 ****64 ****65 ****66 67 3 468 ....69 ....70 ....71 72 4 473 ....74 ....75 ....76 ....77 */

 

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

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

update:

我只是找到了规律,

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

n%i 的数学式子

gcd 的数学式子

 

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
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\n",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 2100 3 3101 4 4102 5 5103 6 6104 7 7105 1000000000 1000000000106 */

 

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

打表

 

看这:

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 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 using namespace std; 9 #define ll long long10 #include
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
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",n,sum);77 }78 return 0;79 }80 /*81 n=2 sum=282 n=3 sum=683 n=4 sum=3684 n=5 sum=32085 n=6 sum=375086 n=7 sum=5443287 n=8 sum=94119288 n=9 sum=1887436889 90 n * (n-1)^(n-2)91 */

 

代码

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 using namespace std; 9 #define ll long long10 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=244 n=3 sum=645 n=4 sum=3646 n=5 sum=32047 n=6 sum=375048 n=7 sum=5443249 n=8 sum=94119250 n=9 sum=1887436851 52 n * (n-1)^(n-2)53 */

 

来自群里的大佬解答

 

证明:

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

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

 

引用另外的大佬一句总结

 

转载于:https://www.cnblogs.com/cmyg/p/11221780.html

你可能感兴趣的文章
apt-get for ubuntu 工具简介
查看>>
数值计算算法-多项式插值算法的实现与分析
查看>>
day8-异常处理与网络编程
查看>>
Python基础-time and datetime
查看>>
shell脚本练习01
查看>>
WPF图标拾取器
查看>>
通过取父级for循环的i来理解闭包,iife,匿名函数
查看>>
HDU 3374 String Problem
查看>>
数据集
查看>>
[Leetcode] unique paths ii 独特路径
查看>>
HDU 1217 Arbitrage (Floyd + SPFA判环)
查看>>
IntelliJ idea学习资源
查看>>
Django Rest Framework -解析器
查看>>
ExtJs 分组表格控件----监听
查看>>
Hibernate二级缓存配置
查看>>
LoadRunner常用术语
查看>>
关于jedis2.4以上版本的连接池配置,及工具类
查看>>
记忆讲师石伟华微信公众号2017所有文章汇总(待更新)
查看>>
FactoryBean
查看>>
Coolite动态加载CheckboxGroup,无法在后台中获取
查看>>