题意:
此题出自2009年IMO中国国家队选拔考试。
思路:
考虑到题目要求苛刻,所以如果能构造出可以解释样例的矩阵,我们就能找到其中的规律。
以 5 8 为例
满足题意的矩阵即:
第一列由 1 ... N 顺序构成
每一行按 1 ... N N ... 1顺序构成
由于答案矩阵本身存在规律
利用规律,我们可以在 O(1) 的时间内求得每行的 sum
一共 N 行,O(N) 得到答案。
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN=10100;
const int INF=0x3f3f3f3f3f3f3f3f;
long long lopsum,tempsum,fans,ans;
int leftt,lop,offset[MAXN];
void ini(){
lopsum=0;
fans=ans=0;
}
int range(int x,int y){
if(x<y) swap(x,y);
return (x+y)*(x-y+1)/2;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=-1){
ini();
for(int i=1;i<=n;i++) lopsum+=i;
for(int i=1;i<=n;i++){
if(i%2==1) offset[i]=i;
else offset[i]=n-offset[i-1];
}
for(int i=1;i<=n;i++){
if(i%2==1){
if(offset[i]>=m){
ans=range(i,i-m+1);
}else{
ans=range(i,1);
leftt=m-offset[i];
//if(i==5001) cout<<offset[i]<<' '<<leftt<<' '<<ans<<endl;
lop=leftt/n;ans+=lop*lopsum;
//if(i==5001) cout<<lop<<endl;
leftt=leftt%n;
if(leftt){
if(lop%2==1){
ans+=range(n,n-leftt+1);
}else{
ans+=range(1,leftt);
}
}
}
}else{
if(offset[i]>=m){
ans=range(i,i+m-1);
}else{
ans=range(i,n);
leftt=m-offset[i];
lop=leftt/n;ans+=lop*lopsum;
leftt=leftt%n;
if(leftt){
if(lop%2==1){
ans+=range(1,leftt);
}else{
ans+=range(n,n-leftt+1);
}
}
}
}
fans=max(fans,ans);
}
cout<<fans<<endl;
}
}
另有O(1)推导
参看点击打开链接