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\)。你可以进行以下两种操作:

  1. 将\(a\)和\(b\)都\(+1\),该操作至多进行一次;
  2. 将\(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 游记的更多相关文章

  1. Codechef October Challenge 2018 游记

    Codechef October Challenge 2018 游记 CHSERVE - Chef and Serves 题目大意: 乒乓球比赛中,双方每累计得两分就会交换一次发球权. 不过,大厨和小 ...

  2. Codechef April Challenge 2019 游记

    Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...

  3. codechef February Challenge 2018 简要题解

    比赛链接:https://www.codechef.com/FEB18,题面和提交记录是公开的,这里就不再贴了 Chef And His Characters 模拟题 Chef And The Pat ...

  4. Codechef STMINCUT S-T Mincut (CodeChef May Challenge 2018) kruskal

    原文链接http://www.cnblogs.com/zhouzhendong/p/9010945.html 题目传送门 - Codechef STMINCUT 题意 在一个有边权的无向图中,我们定义 ...

  5. Codechef September Challenge 2019 Division 2

    Preface 这确实应该是我打过的比较水的CC了(其实就打过两场) 但由于我太弱了打的都是Div2,所以会认为上一场更简单,其实上一场Div的数据结构是真的毒 好了废话不多说快速地讲一下 A Eas ...

  6. Codechef August Challenge 2018 : Chef at the River

    传送门 (要是没有tjm(Sakits)的帮忙,我还真不知道啥时候能做出来 结论是第一次带走尽可能少的动物,使未带走的动物不冲突,带走的这个数量就是最优解. 首先这个数量肯定是下界,更少的话连第一次都 ...

  7. Codechef August Challenge 2018 : Safe Partition

    传送门 (虽然是A了但是不知道复杂度是不是正确的 考虑以某个位置为结尾的合法划分 先考虑min,带来的影响是限制了最小长度,预处理出这个最小长度后,这可以在处理到这个数时,把不能算的部分去掉(不满足m ...

  8. Codechef August Challenge 2018 : Interactive Matrix

    传送门 首先整个矩阵可以被分为很多小矩阵,小矩阵内所有行的单调性是一样的,所有列的单调性是一样的. 考虑如何在这样一个小矩阵中找出答案.我的策略是每次取四个角中最大值和最小值的点,这样可以每次删掉一行 ...

  9. Codechef August Challenge 2018 : Lonely Cycles

    传送门 几波树形dp就行了. #include<cstdio> #include<cstring> #include<algorithm> #define MN 5 ...

随机推荐

  1. Here’s just a fraction of what you can do with linear algebra

    Here’s just a fraction of what you can do with linear algebra The next time someone wonders what the ...

  2. html5 canvas 径向渐变2

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. es6笔记(5)Map数据结构

    概要 字典是用来存储不重复key的Hash结构.不同于集合(Set)的一点,字典使用的是[key,value]的形式来存储数据. JavaScript的对象(Object:{})只能用字符串当做key ...

  4. shiro登录成功之后跳转原路径

    通过 WebUtils.getSavedRequest(request) 来获取shiro保存在session登录之前的url 1:java Controller代码 @PostMapping(&qu ...

  5. Memcached命令:简单获取缓存value用法

    Memcached:命令用法1.cmd 输入telnet ip  端口 进入memcached服务端窗口比如:xxx.Token_T1435622096xxx为key获取此key的memcached ...

  6. mybatis介绍——(一)

    官方API:http://www.mybatis.org/mybatis-3/index.html 中文: http://www.mybatis.org/mybatis-3/zh/index.html ...

  7. mysql学习------二进制日志

    一.什么是二进制日志 1.记录对数据发生或潜在发生更改的sql语句 2.二进制格式保存 3.用途广泛,包括 a.查看数据库变更历史 b.数据库增量备份 c.数据库灾难恢复 d.mysql replic ...

  8. Linux本地解析文件/etc/hosts说明【原创】

    windows的域名本地解析文件hosts是可以一个域名对多个IP,如果有一个IP有问题,可以去解析到其他IP Linux的本地解析文件/etc/hosts,是否也可以这样呢.下面做了个测试 先看一下 ...

  9. python运行execjs解密js

    [转]http://www.knowsky.com/1041161.html python 记一次计算qzonetoken经历 之前用python写了个发表说说的爬虫,但最近发现在post数据时返回不 ...

  10. win10 无法打开 APICloud Studio 2 的解决方案

    坑爹. 新搭建了系统   apicloud studio2  打开无反应 无任何报错提示 双击没有方案.弄了一天 最后搞定. . 百度搜索  win10    null.sys 替换进去 C:/Win ...