链接:http://codeforces.com/contest/407
A Triangle
给出直角三角形的两个直角边,构造出一个三角形顶点均为整数,且每条边不与xy轴平行。构成两个直角边的一定是勾股数。
int get(int x)
{
if(x==1) return 1;
if(!x||x==2||x==3) return 0;
int t=sqrt(1.0*x)+3;
while(t*t>x) t--;
if(t*t==x) return t;
return 0;
}
vector<pair<int,int > > cal(int n)
{
vector<pair<int,int > > V;
int i,j;
for(i=1;i<n;i++)
{
int j=get(n*n-i*i);
if(!j) continue;
V.pb(MP(i,j));
}
return V;
}
int ok(int x1,int y1,int x2,int y2)
{
if(x1*x2+y1*y2) return 0;
if(x1==x2 || y1==y2) return 0;
puts("YES");
puts("0 0");
PR(x1,y1);
PR(x2,y2);
return 1;
}
int ok(pair<int,int > a, pair<int,int > b)
{
int x1=a.first;
int y1=a.second;
int x2=b.first;
int y2=b.second;
int dx[]={1,1,-1,-1};
int dy[]={1,-1,1,-1};
int i,j;
FOR0(i,4) FOR0(j,4)
{
if(ok(x1*dx[i],y1*dy[i],y2*dx[j],x2*dx[j])) return 1;
if(ok(y1*dx[i],x1*dy[i],x2*dx[j],y2*dx[j])) return 1;
}
return 0;
}
int main()
{
int n,m;
RD(n,m);
vector<pair<int,int> > a=cal(n);
vector<pair<int,int> > b=cal(m);
if(SZ(a)==0 || SZ(b)==0)
{
puts("NO");
return 0;
}
int i,j;
FOR0(i,SZ(a)) FOR0(j,SZ(b)) if(ok(a[i],b[j])) return 0;
puts("NO");
}
B Long Path
n+1个房间。第偶数次达到i则下一步到达i+1,否则下一步达到一个指定的房间a[i]=j(1<=j<=i)。从1出发到达n+1的步数。q[i]表示从1开始第一次到达i需要的步数,p[i]表示从1出发第二次到达i的步数,则q[i]=p[i-1]+1,p[i]=q[i]+1+p[a[i]]-q[a[i]]+1+p[i-1]-p[a[i]]。
i64 p[N],q[N];
int n,a[N];
int main()
{
int i;
RD(n);
FOR1(i,n) RD(a[i]);
int j,k;
p[1]=1;
for(i=2;i<=n;i++)
{
q[i]=p[i-1]+1;
if(a[i]==i) p[i]=q[i]+1;
else
{
if(a[i]==1) p[i]=q[i]+1+p[i-1]+1;
else p[i]=q[i]+1+p[a[i]]-q[a[i]]+1+p[i-1]-p[a[i]];
}
p[i]%=mod;
q[i]%=mod;
}
int ans=p[n]+1;
ans%=mod;
if(ans<0) ans+=mod;
PR(ans);
}
C. Curious Array
给出一个数列A,m个操作,每个操作给出L,R,k,对于L<=j<=R,将A[j]加上C(j-L+k,k)。最后输出A。C(n,k)-C(n-1,k)=C(n-1,k-1)。假如有操作L=1,R=5,k=4,那么1到5加上的数字分别为C(4,4),C(5,4),C(6,4),C(7,4),C(8,4),
1
1 1 1 1 1 1
1 2 3 4 5 6
1 3 6 10 15 21
1 4 10 20 35 56
1 5 15 35 70 126
因此设置一个数组f[K][N],将f[k+1][L]加上1即可,最后一层层向上叠加。同时f[i][R+1]将减去某个数以抵消影响。
int C[N][105];
void init()
{
int i,j;
C[0][0]=1;
for(i=1;i<N;i++)
{
C[i][0]=1;
for(j=1;j<=101;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
}
int a[N],f[105][N],n,m;
int main()
{
init();
RD(n,m);
int i,j,k;
FOR1(i,n) a[i]=getInt();
while(m--)
{
int L,R,k;
RD(L,R,k);
(f[k+1][L]+=1)%=mod;
for(i=1;i<=k+1;i++)
{
(f[i][R+1]-=C[R-L+k+1-i][k+1-i])%=mod;
}
}
for(i=100;i>=0;i--)
{
k=0;
for(j=1;j<=n;j++)
{
(k+=f[i+1][j])%=mod;
(f[i][j]+=k)%=mod;
}
}
for(i=1;i<=n;i++)
{
(f[0][i]+=a[i])%=mod;
if(f[0][i]<0) f[0][i]+=mod;
printf("%d",f[0][i]);
if(i<n) putchar(' ');
}
puts("");
}
D. Largest Submatrix 3
给出一个矩阵,找出一个最大的的子矩阵是使得子矩阵内的数字各不相同。用一个map:mp[x][j]表示第j列的数字x上一次出现的行数。用f[a][b]表示当前行的列区间[a,b]向上最大的延伸长度。用(i+1-f[a][b])*(b-a+1)更新答案。
int a[N][N],n,m,f[N][N];
map<int,int> mp[N*N];
int main()
{
RD(n,m);
int i,j,k,t;
FOR0(i,n) FOR0(j,m) RD(a[i][j]);
int ans=0;
FOR0(i,n)
{
FOR0(j,m)
{
map<int,int>::iterator it;
int x=a[i][j];
for(it=mp[x].begin();it!=mp[x].end();it++)
{
int a=it->first;
int b=j;
if(a>b) swap(a,b);
upMax(f[a][b],it->second);
}
mp[x][j]=i+1;
}
for(t=1;t<m;t++) for(k=0;k+t<m;k++)
{
upMax(f[k][k+t],f[k][k+t-1]);
upMax(f[k][k+t],f[k+1][k+t]);
}
for(t=0;t<m;t++) for(k=t;k<m;k++)
{
upMax(ans,(i-f[t][k]+1)*(k-t+1));
}
}
PR(ans);
}