Codechef September Challenge 2018 游记
Codechef September Challenge 2018 游记
Magician versus Chef
题目大意:
有一排\(n(n\le10^5)\)个格子,一开始硬币在第\(x\)个格子里。\(m(m\le10^4)\)次操作,每次交换指定的两个格子。问最后硬币在第几个格子里。
思路:
按题意模拟即可。
源代码:
#include<cstdio>
#include<cctype>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
int main() {
for(register int T=getint();T;T--) {
const int n=getint();
int x=getint();
for(register int s=getint();s;s--) {
const int a=getint(),b=getint();
if(a==x) {
x=b;
} else if(b==x) {
x=a;
}
}
printf("%d\n",x);
}
return 0;
}
Chef and Adventures
题目大意:
你有两个属性\(a\)和\(b\),一开始\(a=b=1\)。你可以进行以下两种操作:
- 将\(a\)和\(b\)都\(+1\),该操作至多进行一次;
- 将\(a+=x\),\(b+=y\)。
问最后能否使\(a=n\),\(b=m\)。
思路:
枚举是否进行第一种操作,然后直接取模判断是否可行即可。
源代码:
#include<cstdio>
#include<cctype>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
int main() {
for(register int T=getint();T;T--) {
const int n=getint()-1,m=getint()-1,x=getint(),y=getint();
if(n%x==0&&m%y==0) {
puts("Chefirnemo");
continue;
}
if(n&&m&&(n-1)%x==0&&(m-1)%y==0) {
puts("Chefirnemo");
continue;
}
puts("Pofik");
}
return 0;
}
War of XORs
题目大意:
给你一个数列\(A_{1\sim n}(n\le10^5,A_i\le10^6)\),求满足\(1\le i<j\le n\)的数对\((i,j)\)的个数,使得\(A_i\oplus A_j\)可以写成两个奇偶性相同的质数的和。
思路:
根据哥德巴赫猜想,题目想问的就是异或起来的结果是偶数(不包括\(0\)和\(2\))的数对个数。
源代码:
#include<cstdio>
#include<cctype>
#include<cstring>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
typedef long long int64;
const int A=1<<20;
int cnt[2],set[A];
int64 tmp[2];
int main() {
for(register int T=getint();T;T--) {
memset(set,0,sizeof set);
cnt[0]=cnt[1]=tmp[0]=tmp[1]=0;
const int n=getint();
for(register int i=0;i<n;i++) {
const int x=getint();
tmp[0]+=set[x];
tmp[1]+=set[x^2];
set[x]++;
cnt[x&1]++;
}
printf("%lld\n",(int64)cnt[0]*(cnt[0]-1)/2+(int64)cnt[1]*(cnt[1]-1)/2-tmp[0]-tmp[1]);
}
return 0;
}
Bad Shuffle
题目大意:
按如下方式生成一个长度为\(n(n\le17)\)的排列:
P := [1, 2, ..., N]
for i in 1..N do
j := rand(1, N)
swap(P[i], P[j])
用\(p(P)\)表示排列\(P\)被生成的概率,求\(p(P)\)最小的\(P\)和\(p(P)\)最大的\(P\)。如有多种,输出任意一种即可。
思路:
找规律。
源代码:
#include<cstdio>
#include<cctype>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
int main() {
const int n=getint();
for(register int i=2;i<=n/2;i++) printf("%d ",i);
printf("%d ",1);
for(register int i=n/2+2;i<=n;i++) printf("%d ",i);
printf("%d\n",n/2+1);
for(register int i=1;i<=n;i++) {
printf("%d%c",(i-2+n)%n+1," \n"[i==n]);
}
return 0;
}
Table Game
题目大意:
Alice和Bob在玩桌游:有一张\((n+1)\times(m+1)(n,m\le10^5)\)的桌子,在上面进行游戏。记第\(i\)行第\(j\)列的格子为\((i,j)(0\le i\le n,0\le j\le m)\),游戏规则如下:
- 初始时,桌上某个格子中有一块石头。
- 双方轮流操作,Alice执先手。
- 每回合中,当前玩家需要将石头从其当前格子(记为\((x,y)\))移动到\((x−1,y)\)或\((x,y−1)\)。
- 当石头被移动到的位置\((x,y)\)满足\(x=0\)或\(y=0\)时,游戏结束。
- 胜者由进行最后一回合的玩家以及游戏结束时石头所处的格子共同决定,这一信息在输入中给出。请注意,石头一定不会到达 \((0,0)\)。
你需要回答\(q(q\le10^5)\)个询问,每个询问给定石头的初始位置\((x,y)\),你需要求出游戏的胜者。
思路:
观察发现只需要求出前两行/列是必胜态还是必败态,其余可以通过前面的状态算出来。
源代码:
#include<cstdio>
#include<cctype>
#include<cstring>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=1e5+1;
bool b[3][N],c[N][3];
char s[N];
int main() {
for(register int T=getint();T;T--) {
scanf("%s",s);
const int m=strlen(s);
for(register int i=0;i<m;i++) {
b[0][i+1]=s[i]^'0';
if(i+1<=2) c[0][i+1]=s[i]^'0';
}
scanf("%s",s);
const int n=strlen(s);
for(register int i=0;i<n;i++) {
c[i+1][0]=s[i]^'0';
if(i+1<=2) b[i+1][0]=s[i]^'0';
}
for(register int i=1;i<=2;i++) {
for(register int j=1;j<=m;j++) {
b[i][j]=!b[i][j-1]||!b[i-1][j];
}
}
for(register int j=1;j<=2;j++) {
for(register int i=1;i<=n;i++) {
c[i][j]=!c[i][j-1]||!c[i-1][j];
}
}
const int q=getint();
for(register int i=0;i<q;i++) {
const int x=getint(),y=getint();
if(x<=2) {
printf("%d",b[x][y]);
continue;
}
if(y<=2) {
printf("%d",c[x][y]);
continue;
}
if(x<y) {
printf("%d",b[2][y-(x-2)]);
} else {
printf("%d",c[x-(y-2)][2]);
}
}
puts("");
}
return 0;
}
Sasha and Photos
题目大意:
两个尺寸\(h_1\cdot w_1\)和\(h_2\cdot w_2(h_1w_1,h_2w_2\le10^6)\)的黑白照片,你将它放大成两个\(\operatorname{lcm}(h_1,h_2)\cdot\operatorname{lcm}(w_1,w_2)\)的照片,问两张照片有多少对应位置颜色相等。
思路:
枚举一张照片上原有的格子,求出在新照片上对应另一张照片的哪些格子。使用前缀和统计即可。
源代码:
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
#define int long long
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
inline bool getbit() {
register char ch;
while(!isdigit(ch=getchar()));
return ch^'0';
}
const int N=1e6;
std::vector<int> a[N],b[N];
inline int sum(const int &x,const int &y,const bool &t) {
int ret=b[x][y];
if(x!=0) ret-=b[x-1][y];
if(y!=0) ret-=b[x][y-1];
if(x!=0&&y!=0) ret+=b[x-1][y-1];
if(t==0) ret=1-ret;
return ret;
}
inline int sum(const int &x0,const int &y0,const int &x1,const int &y1,const bool &t) {
if(x0>x1||y0>y1) return 0;
int ret=b[x1][y1];
if(x0!=0) ret-=b[x0-1][y1];
if(y0!=0) ret-=b[x1][y0-1];
if(x0!=0&&y0!=0) ret+=b[x0-1][y0-1];
if(t==0) ret=(x1-x0+1)*(y1-y0+1)-ret;
return ret;
}
int area(const int &x,const int &y) {
return std::max(x,0ll)*std::max(y,0ll);
}
signed main() {
for(register int T=getint();T;T--) {
const int h1=getint(),w1=getint();
for(register int i=0;i<h1;i++) {
a[i].resize(w1);
for(register int j=0;j<w1;j++) {
a[i][j]=getbit();
}
}
const int h2=getint(),w2=getint();
for(register int i=0;i<h2;i++) {
b[i].resize(w2);
for(register int j=0;j<w2;j++) {
b[i][j]=getbit();
if(i!=0) b[i][j]+=b[i-1][j];
if(j!=0) b[i][j]+=b[i][j-1];
if(i!=0&&j!=0) b[i][j]-=b[i-1][j-1];
}
}
const int h0=std::__gcd(h1,h2),w0=std::__gcd(w1,w2);
int ans=0;
for(register int i=0;i<h1;i++) {
const int a1=i*h2/h0,b1=(i+1)*h2/h0-1;
for(register int j=0;j<w1;j++) {
const int c1=j*w2/w0,d1=(j+1)*w2/w0-1;
const bool &t=a[i][j];
const int u=a1/(h1/h0),d=b1/(h1/h0);
const int l=c1/(w1/w0),r=d1/(w1/w0);
ans+=sum(u,l,t)*area(std::min((u+1)*h1/h0-1,b1)-a1+1,std::min((l+1)*w1/w0-1,d1)-c1+1);
if(l!=r) ans+=sum(u,r,t)*area(std::min((u+1)*h1/h0-1,b1)-a1+1,d1-std::max(r*w1/w0,c1)+1);
if(u!=d) ans+=sum(d,l,t)*area(b1-std::max(d*h1/h0,a1)+1,std::min((l+1)*w1/w0-1,d1)-c1+1);
if(u!=d&&l!=r) ans+=sum(d,r,t)*area(b1-std::max(d*h1/h0,a1)+1,d1-std::max(r*w1/w0,c1)+1);
ans+=sum(u,l+1,u,r-1,t)*area(std::min((u+1)*h1/h0-1,b1)-a1+1,w1/w0);
if(u!=d) ans+=sum(d,l+1,d,r-1,t)*area(b1-std::max(d*h1/h0,a1)+1,w1/w0);
ans+=sum(u+1,l,d-1,l,t)*area(h1/h0,std::min((l+1)*w1/w0-1,d1)-c1+1);
if(l!=r) ans+=sum(u+1,r,d-1,r,t)*area(h1/h0,d1-std::max(r*w1/w0,c1)+1);
ans+=sum(u+1,l+1,d-1,r-1,t)*area(h1/h0,w1/w0);
}
}
printf("%lld\n",ans);
for(register int i=0;i<h1;i++) a[i].clear();
for(register int i=0;i<h2;i++) b[i].clear();
}
return 0;
}
AND Square Subsegments
题目大意:
给你一个长度为\(n(n\le10^5)\)的数列\(A(A_i<2^30)\)。\(q(q\le5\times10^5)\)次询问,每次询问\(A_{[l,r]}\)中有多少子序列满足所有数按位与的结果是完全平方数。
思路:
将询问离线,按右端点排序。考虑加入一个数作为右端点。对于一个右端点\(A_r\),向左不断按位与后,一旦某一位变成\(0\)就再也不能变回\(1\)了。因此根据按位与的结果最多可以分成\(30\)段。
看一下这一段对应的结果是否是完全平方数,如果是就将对应的区间\(+1\)。线段树维护即可。
源代码:
#include<cmath>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<algorithm>
#include<functional>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
using int64=long long;
const int N=1e5+1,B=30,M=5e5;
struct Query {
int l,r,id;
bool operator < (const Query &rhs) const {
return r<rhs.r;
}
};
Query q[M];
int a[N],pos[B];
int64 ans[M];
std::vector<std::pair<int,int>> tmp;
inline bool check(const int &x) {
return floor(sqrt(x))*floor(sqrt(x))==x;
}
class SegmentTree {
#define _left <<1
#define _right <<1|1
#define mid ((b+e)>>1)
private:
int tag[N<<2];
int64 val[N<<2];
int len(const int &b,const int &e) const {
return e-b+1;
}
void push_down(const int &p,const int &b,const int &e) {
if(tag[p]==0) return;
tag[p _left]+=tag[p];
tag[p _right]+=tag[p];
val[p _left]+=tag[p]*len(b,mid);
val[p _right]+=tag[p]*len(mid+1,e);
tag[p]=0;
}
void push_up(const int &p) {
val[p]=val[p _left]+val[p _right];
}
public:
void build(const int &p,const int &b,const int &e) {
val[p]=tag[p]=0;
if(b==e) return;
build(p _left,b,mid);
build(p _right,mid+1,e);
}
void modify(const int &p,const int &b,const int &e,const int &l,const int &r) {
if(b==l&&e==r) {
tag[p]++;
val[p]+=len(b,e);
return;
}
push_down(p,b,e);
if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r));
if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r);
push_up(p);
}
int64 query(const int &p,const int &b,const int &e,const int &l,const int &r) {
if(b==l&&e==r) return val[p];
push_down(p,b,e);
int64 ret=0;
if(l<=mid) ret+=query(p _left,b,mid,l,std::min(mid,r));
if(r>mid) ret+=query(p _right,mid+1,e,std::max(mid+1,l),r);
return ret;
}
#undef _left
#undef _right
#undef mid
};
SegmentTree t;
int main() {
for(register int T=getint();T;T--) {
memset(pos,0,sizeof pos);
const int n=getint(),m=getint();
t.build(1,1,n);
for(register int i=1;i<=n;i++) {
a[i]=getint();
}
for(register int i=0;i<m;i++) {
q[i].l=getint();
q[i].r=getint();
q[i].id=i;
}
std::sort(&q[0],&q[m]);
for(register int i=1,j=0;i<=n&&j<m;i++) {
tmp.clear();
for(register int j=0;j<B;j++) {
if((a[i]>>j)%2==0) {
pos[j]=i;
} else {
tmp.push_back(std::make_pair(pos[j],j));
}
}
std::sort(tmp.begin(),tmp.end(),std::greater<std::pair<int,int>>());
int last=i;
for(register unsigned j=0;j<tmp.size();j++) {
if(check(a[i])&&tmp[j].first!=last) {
t.modify(1,1,n,tmp[j].first+1,last);
}
a[i]^=1<<tmp[j].second;
last=tmp[j].first;
}
if(check(a[i])&&last!=0) {
t.modify(1,1,n,1,last);
}
for(;j<m&&q[j].r==i;j++) {
ans[q[j].id]=t.query(1,1,n,q[j].l,q[j].r);
}
}
for(register int i=0;i<m;i++) {
printf("%lld\n",ans[i]);
}
}
return 0;
}
Chef and Condition Zero (Challenge)
题目大意:
给你一个\(n\times m(n,m\le1000)\)的网格,每个格子都有一个权值\(w_{i,j}\),请你尝试构造一种方案,将该网格图分成四连通的\(k(k\le1000)\)块,使得权值和最大的块的权值与权值和最小的块的权值之差尽量小。
思路:
普通贪心。将所有权值之和\(\div k\)作为参照。每次分块尽量接近这个数,并将差值加入下一次分块中。用各种顺序跑一边去个最小值。
按照考场上最后的评分参数得到\(197.67829\)分。
源代码:
#include<cstdio>
#include<cctype>
#include<climits>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
typedef long long int64;
const int N=1001;
int n,m,k,a[N][N],sid;
long double ans=1e18;
int64 avg,del,tot;
namespace sol01 {
int b[N][N];
int64 sum[N];
void main() {
del=0;
int cnt=1;
for(register int i=1;i<=n;i++) {
if(i&1) {
for(register int j=1;j<=m;j++) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
} else {
for(register int j=m;j>=1;j--) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
}
}
int64 max=LLONG_MIN,min=LLONG_MAX;
for(register int i=1;i<=cnt;i++) {
max=std::max(max,sum[i]);
min=std::min(min,sum[i]);
}
if((max-min)*1e9/tot<ans) {
ans=(max-min)*1e9/tot;
sid=1;
}
}
void print() {
for(register int i=1;i<=n;i++) {
for(register int j=1;j<=m;j++) {
printf("%d%c",b[i][j]," \n"[j==m]);
}
}
}
};
namespace sol02 {
int b[N][N];
int64 sum[N];
void main() {
del=0;
int cnt=1;
for(register int i=1;i<=n;i++) {
if(!(i&1)) {
for(register int j=1;j<=m;j++) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
} else {
for(register int j=m;j>=1;j--) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
}
}
int64 max=LLONG_MIN,min=LLONG_MAX;
for(register int i=1;i<=cnt;i++) {
max=std::max(max,sum[i]);
min=std::min(min,sum[i]);
}
if((max-min)*1e9/tot<ans) {
ans=(max-min)*1e9/tot;
sid=2;
}
}
void print() {
for(register int i=1;i<=n;i++) {
for(register int j=1;j<=m;j++) {
printf("%d%c",b[i][j]," \n"[j==m]);
}
}
}
};
namespace sol03 {
int b[N][N];
int64 sum[N];
void main() {
del=0;
int cnt=1;
for(register int j=1;j<=m;j++) {
if(!(j&1)) {
for(register int i=1;i<=n;i++) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
} else {
for(register int i=n;i>=1;i--) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
}
}
int64 max=LLONG_MIN,min=LLONG_MAX;
for(register int i=1;i<=cnt;i++) {
max=std::max(max,sum[i]);
min=std::min(min,sum[i]);
}
if((max-min)*1e9/tot<ans) {
ans=(max-min)*1e9/tot;
sid=3;
}
}
void print() {
for(register int i=1;i<=n;i++) {
for(register int j=1;j<=m;j++) {
printf("%d%c",b[i][j]," \n"[j==m]);
}
}
}
};
namespace sol04 {
int b[N][N];
int64 sum[N];
void main() {
del=0;
int cnt=1;
for(register int j=1;j<=m;j++) {
if(j&1) {
for(register int i=1;i<=n;i++) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
} else {
for(register int i=n;i>=1;i--) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
}
}
int64 max=LLONG_MIN,min=LLONG_MAX;
for(register int i=1;i<=cnt;i++) {
max=std::max(max,sum[i]);
min=std::min(min,sum[i]);
}
if((max-min)*1e9/tot<ans) {
ans=(max-min)*1e9/tot;
sid=4;
}
}
void print() {
for(register int i=1;i<=n;i++) {
for(register int j=1;j<=m;j++) {
printf("%d%c",b[i][j]," \n"[j==m]);
}
}
}
};
namespace sol05 {
int b[N][N];
int64 sum[N];
void main() {
del=0;
int cnt=1;
for(register int i=n;i>=1;i--) {
if(i&1) {
for(register int j=1;j<=m;j++) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
} else {
for(register int j=m;j>=1;j--) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
}
}
int64 max=LLONG_MIN,min=LLONG_MAX;
for(register int i=1;i<=cnt;i++) {
max=std::max(max,sum[i]);
min=std::min(min,sum[i]);
}
if((max-min)*1e9/tot<ans) {
ans=(max-min)*1e9/tot;
sid=5;
}
}
void print() {
for(register int i=1;i<=n;i++) {
for(register int j=1;j<=m;j++) {
printf("%d%c",b[i][j]," \n"[j==m]);
}
}
}
};
namespace sol06 {
int b[N][N];
int64 sum[N];
void main() {
del=0;
int cnt=1;
for(register int i=n;i>=1;i--) {
if(!(i&1)) {
for(register int j=1;j<=m;j++) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
} else {
for(register int j=m;j>=1;j--) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
}
}
int64 max=LLONG_MIN,min=LLONG_MAX;
for(register int i=1;i<=cnt;i++) {
max=std::max(max,sum[i]);
min=std::min(min,sum[i]);
}
if((max-min)*1e9/tot<ans) {
ans=(max-min)*1e9/tot;
sid=6;
}
}
void print() {
for(register int i=1;i<=n;i++) {
for(register int j=1;j<=m;j++) {
printf("%d%c",b[i][j]," \n"[j==m]);
}
}
}
};
namespace sol07 {
int b[N][N];
int64 sum[N];
void main() {
del=0;
int cnt=1;
for(register int j=m;j>=1;j--) {
if(!(j&1)) {
for(register int i=1;i<=n;i++) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
} else {
for(register int i=n;i>=1;i--) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
}
}
int64 max=LLONG_MIN,min=LLONG_MAX;
for(register int i=1;i<=cnt;i++) {
max=std::max(max,sum[i]);
min=std::min(min,sum[i]);
}
if((max-min)*1e9/tot<ans) {
ans=(max-min)*1e9/tot;
sid=7;
}
}
void print() {
for(register int i=1;i<=n;i++) {
for(register int j=1;j<=m;j++) {
printf("%d%c",b[i][j]," \n"[j==m]);
}
}
}
};
namespace sol08 {
int b[N][N];
int64 sum[N];
void main() {
del=0;
int cnt=1;
for(register int j=m;j>=1;j--) {
if(j&1) {
for(register int i=1;i<=n;i++) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
} else {
for(register int i=n;i>=1;i--) {
if(cnt<k&&sum[cnt]+a[i][j]>avg+del) {
del=avg+del-sum[cnt++];
}
b[i][j]=cnt;
sum[cnt]+=a[i][j];
}
}
}
int64 max=LLONG_MIN,min=LLONG_MAX;
for(register int i=1;i<=cnt;i++) {
max=std::max(max,sum[i]);
min=std::min(min,sum[i]);
}
if((max-min)*1e9/tot<ans) {
ans=(max-min)*1e9/tot;
sid=8;
}
}
void print() {
for(register int i=1;i<=n;i++) {
for(register int j=1;j<=m;j++) {
printf("%d%c",b[i][j]," \n"[j==m]);
}
}
}
};
int main() {
n=getint(),m=getint(),k=getint();
for(register int i=1;i<=n;i++) {
for(register int j=1;j<=m;j++) {
a[i][j]=getint();
avg+=a[i][j];
}
}
tot=avg;
avg/=k;
sol01::main();
sol02::main();
sol03::main();
sol04::main();
sol05::main();
sol06::main();
sol07::main();
sol08::main();
if(sid==1) sol01::print();
if(sid==2) sol02::print();
if(sid==3) sol03::print();
if(sid==4) sol04::print();
if(sid==5) sol05::print();
if(sid==6) sol06::print();
if(sid==7) sol07::print();
if(sid==8) sol08::print();
return 0;
}
Codechef September Challenge 2018 游记的更多相关文章
- Codechef October Challenge 2018 游记
Codechef October Challenge 2018 游记 CHSERVE - Chef and Serves 题目大意: 乒乓球比赛中,双方每累计得两分就会交换一次发球权. 不过,大厨和小 ...
- Codechef April Challenge 2019 游记
Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...
- codechef February Challenge 2018 简要题解
比赛链接:https://www.codechef.com/FEB18,题面和提交记录是公开的,这里就不再贴了 Chef And His Characters 模拟题 Chef And The Pat ...
- Codechef STMINCUT S-T Mincut (CodeChef May Challenge 2018) kruskal
原文链接http://www.cnblogs.com/zhouzhendong/p/9010945.html 题目传送门 - Codechef STMINCUT 题意 在一个有边权的无向图中,我们定义 ...
- Codechef September Challenge 2019 Division 2
Preface 这确实应该是我打过的比较水的CC了(其实就打过两场) 但由于我太弱了打的都是Div2,所以会认为上一场更简单,其实上一场Div的数据结构是真的毒 好了废话不多说快速地讲一下 A Eas ...
- Codechef August Challenge 2018 : Chef at the River
传送门 (要是没有tjm(Sakits)的帮忙,我还真不知道啥时候能做出来 结论是第一次带走尽可能少的动物,使未带走的动物不冲突,带走的这个数量就是最优解. 首先这个数量肯定是下界,更少的话连第一次都 ...
- Codechef August Challenge 2018 : Safe Partition
传送门 (虽然是A了但是不知道复杂度是不是正确的 考虑以某个位置为结尾的合法划分 先考虑min,带来的影响是限制了最小长度,预处理出这个最小长度后,这可以在处理到这个数时,把不能算的部分去掉(不满足m ...
- Codechef August Challenge 2018 : Interactive Matrix
传送门 首先整个矩阵可以被分为很多小矩阵,小矩阵内所有行的单调性是一样的,所有列的单调性是一样的. 考虑如何在这样一个小矩阵中找出答案.我的策略是每次取四个角中最大值和最小值的点,这样可以每次删掉一行 ...
- Codechef August Challenge 2018 : Lonely Cycles
传送门 几波树形dp就行了. #include<cstdio> #include<cstring> #include<algorithm> #define MN 5 ...
随机推荐
- Java日期比较
在进行业务处理时,遇到一个需要比较日期但是不包含时分秒的判断问题 SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); ...
- HDU 3094 树上删边 NIM变形
基本的树上删边游戏 写过很多遍了 /** @Date : 2017-10-13 18:19:37 * @FileName: HDU 3094 树上删边 NIM变形.cpp * @Platform: W ...
- Nginx ab压力测试
20-ab压力测试及nginx性能统计模块 优化的启发,打开的文件太多 Nginx 错误日志显示,打开文件数太多 系统层面 more /proc/sys/net/core/somaxconn 单个Ng ...
- Sortable.js
拖拽的时候主要由这几个事件完成, ondragstart 事件:当拖拽元素开始被拖拽的时候触发的事件,此事件作用在被拖曳元素上 ondragenter 事件:当拖曳元素进入目标元素的时候触发的事件,此 ...
- Python 入门基础3 --流程控制
今日目录: 一.流程控制 1. if 2. while 3. for 4. 后期补充内容 一.流程控制--if 1.if判断: # if判断 age = 21 weight = 50 if age & ...
- spring的普通类中获取session和request对像
在使用spring时,经常需要在普通类中获取session,request等对像. 1.第一钟方式,针对Spring和Struts2集成的项目: 在有使用struts2时,因为struts2有一个接口 ...
- L0,L1,L2范数,正则化,过拟合
L0范数是指向量中非0元素的个数 L1范数是向量中各个元素的绝对值求和 L2范数是指向量的各个元素平方求和然后取和的平方根 机器学习的目的是使学习到的模型不仅对已知的数据而且对未知的数据有很好的预测能 ...
- imperva—waf 敏感字段显现
imperva WAF中看到的日志内容信息有些都是敏感的 比如登录登出的信息 如何调整敏感信息的现实方式,并可以自定义敏感字段? 这里添加字段就可以了 这样就将******转变为明文了
- Webservice soap wsdl区别之个人见解
原文:http://blog.csdn.net/pautcher_0/article/details/6798351 Web Service实现业务诉求:Web Service是真正“办事”的那个,提 ...
- springcloud微服务架构搭建:服务调用
spring-cloud调用服务有两种方式,一种是Ribbon+RestTemplate, 另外一种是Feign. Ribbon是一个基于HTTP和TCP客户端的负载均衡器,类似nginx反向代理,可 ...