A矩阵
时间限制:1秒 空间限制:131072K
题目描述
给出一个n * m的矩阵。让你从中发现一个最大的正方形。使得这样子的正方形在矩阵中出现了至少两次。输出最大正方形的边长。
输入描述:
第一行两个整数n, m代表矩阵的长和宽; 接下来n行,每行m个字符(小写字母),表示矩阵;
输出描述:
输出一个整数表示满足条件的最大正方形的边长。
示例1
输入
5 10 ljkfghdfas isdfjksiye pgljkijlgp eyisdafdsi lnpglkfkjl
输出
3
备注:
对于30%的数据,n,m≤100; 对于100%的数据,n,m≤500;
hash好题,推荐去卿学姐讲堂学hash
每一个字符串都hash一下和长度有关的哈希值
#include<cstdio> #include<algorithm> #define N 510 typedef unsigned long long LL; const LL D1=101,D2=193; int n,m,i,j,l,r,mid,ans,t; char a[N][N]; LL pow1[N],pow2[N],h[N][N],tmp,tmp2,has[N*N]; bool check(int x) { for(i=1; i<=n; i++) { for(tmp=0,j=1; j<x; j++) tmp=tmp*D1+a[i][j],h[i][j]=0; for(j=x; j<=m; j++) { h[i][j]=tmp=tmp*D1-pow1[x]*a[i][j-x]+a[i][j]; } } for(t=0,i=x; i<=m; i++) { for(tmp=0,j=1; j<x; j++) tmp=tmp*D2+h[j][i]; for(j=x; j<=n; j++) { has[t++]=tmp=tmp*D2-pow2[x]*h[j-x][i]+h[j][i]; } } std::sort(has,has+t); for(i=1; i<t; i++) if(has[i-1]==has[i]) return 1; return 0; } int main() { scanf("%d%d",&n,&m); for(i=1; i<=n; i++) { scanf("%s",a[i]+1); for(j=1; j<=m; j++) a[i][j]-='a'-1; } l=1,r=n<m?n:m; for(pow1[0]=pow2[0]=i=1; i<=r; i++) pow1[i]=pow1[i-1]*D1, pow2[i]=pow2[i-1]*D2; while(l<=r) if(check(mid=(l+r)>>1)) l=(ans=mid)+1; else r=mid-1; return printf("%d",ans),0; }
B树
时间限制:1秒 空间限制:131072K
题目描述
shy有一颗树,树有n个结点。有k种不同颜色的染料给树染色。一个染色方案是合法的,当且仅当对于所有相同颜色的点对(x,y),x到y的路径上的所有点的颜色都要与x和y相同。请统计方案数。
输入描述:
第一行两个整数n,k代表点数和颜色数; 接下来n-1行,每行两个整数x,y表示x与y之间存在一条边;
输出描述:
输出一个整数表示方案数(mod 1e9+7)。
示例1
输入
4 3 1 2 2 3 2 4
输出
39
备注:
对于30%的数据,n≤10, k≤3; 对于100%的数据,n,k≤300。
B这个是个假树啊,只要找到组合数的贡献是k*(k-1)*……*(k-i)就好的
#include <stdio.h> const int MD=1e9+7; int dp[301][301]; int main() { int n,k; scanf("%d%d",&n,&k); dp[0][0]=1; for(int i=1; i<n; i++) { dp[i][0]=1; for(int j=1; j<=i; j++) dp[i][j]=(dp[i-1][j-1]+dp[i-1][j])%MD; } int kk=k,ans=0; for(int i=0;i<=k&&i<=n;i++) { ans=(ans+dp[n-1][i]*1LL*kk%MD)%MD; kk=1LL*kk*(k-i-1)%MD; } printf("%d",ans); return 0; }