E
签到题
题意:给定N, k,输出一个排列,满足:存在一段长度为i的子序列,其和模N余k(
1
≤
i
≤
N
1\leq i\leq N
1≤i≤N)。
思路:如果存在,
n
∗
(
n
+
1
)
2
=
k
(
m
o
d
N
)
\frac{n*(n+1)}{2} = k (mod N)
2n∗(n+1)=k(modN)。
如果是奇数,输出N 1 N-1 2 N-2 ……
如果是奇数,输出N
N
2
\frac{N}{2}
2N, 1 N-1 2 N-2 ……
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
int n,k;
scanf("%d%d",&n,&k);
if(n%2==1)
{
if(k==0)
{
printf("%d ",n);
for(int i=1;i<=n/2;i++)
printf("%d %d ",i,n-i);
return 0;
}
else
{
printf("-1");
return 0;
}
}
if(n/2!=k)
{
printf("-1");
return 0;
}
printf("%d %d ",n,n/2);
for(int i=1;i<n/2;i++)
printf("%d %d ",i,n-i);
return 0;
}
G
题意:给一个n*n的格子,k种颜色,给格子的边框染颜色,要求,每一行/列至少两种颜色,每一个格子的四条边至少有两种颜色。每种颜色用过的次数相同。
思路:先考虑染横行,如果一个格子的上下两条边不同色,那么一定不同色。如果n%k!=0,那么直接横着按1 ~ k轮流染就可以了。否则,奇数行和偶数行错开就行了。纵行类似染法。
但是,染完横行后直接再输出一遍当成纵行的方法是错的。因为k可能大于2n(n+1)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
const int N=410;
int f[N][N],g[N][N];
int main()
{
int T,n,k,cnt;
scanf("%d",&T);
while(T)
{
T--;
scanf("%d%d",&n,&k);
if((2*n*(n+1))%k!=0||n==1||k==1)
{
printf("-1\n");
continue;
}
if(n%k==0)
{
for(int i=1;i<=n+1;i++)
{
if(i%2==1)
cnt=0;
else
cnt=1;
for(int j=1;j<=n;j++)
{
f[i][j]=cnt+1;
cnt=(cnt+1)%k;
}
}
for(int i=1;i<=n+1;i++)
{
for(int j=1;j<=n;j++)
printf("%d ",f[i][j]);
printf("\n");
}
for(int i=1;i<=n+1;i++)
{
for(int j=1;j<=n;j++)
printf("%d ",f[i][j]);
printf("\n");
}
}
else
{
cnt=0;
for(int i=1;i<=n+1;i++)
for(int j=1;j<=n;j++)
{
f[i][j]=cnt+1;
cnt=(cnt+1)%k;
}
for(int i=1;i<=n+1;i++)
{
for(int j=1;j<=n;j++)
{
g[i][j]=cnt+1;
cnt=(cnt+1)%k;
}
}
for(int i=1;i<=n+1;i++)
{
for(int j=1;j<=n;j++)
printf("%d ",f[i][j]);
printf("\n");
}
for(int i=1;i<=n+1;i++)
{
for(int j=1;j<=n;j++)
printf("%d ",g[i][j]);
printf("\n");
}
}
}
return 0;
}