2020牛客暑期多校第六场
G.Grid-Coloring
算法标签:构造
其实感觉是比较宽松的构造题,比赛的时候没想到判n==1的情况,调了一个多小时没发现,赛后加上就过了,有点伤。。我个人的思路是先用红蓝两种颜色染色,只要每行每列颜色都是交替的就肯定能满足条件了。
然后再用把某一部分蓝色或者红色改变成其他颜色,因为只要保证这个颜色只从蓝色或者只从红色改变而来,改变之后肯定还是满足条件的。
对于k是偶数的情况,恰好可以一半给蓝色,一半给红色,但对于k是奇数的情况,就不可避免会有一种颜色同时从蓝色红色改变而来。此时只需要考虑怎么安排这一种颜色就可以了。。答案是一半选择水平的蓝色,一半选择竖直的红色。对于剩下的,再按照k为偶数的情况分配即可。具体证明涉及一点数学计算,主要是奇偶性方面的,其实也不难推,这里就不浪费时间了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int col[N];
int n,k,T;
void sol()
{
cin>>n>>k;
int sum=2*n*(n+1);
for (int i=1;i<=sum;i++) col[i]=0;
if (sum%k!=0 || k==1 || n==1)
{
printf("-1\n");
return;
}
int t1=1,t2=sum/2+1;
if (k%2==1)
{
int tot=sum/k;
for (int i=1;i<=tot/2;i++) col[i]=k,col[i+sum/2]=k;
t1+=tot/2;
t2+=tot/2;
}
for (int i=1;i<=k/2*2;i++)
{
if (t1<=sum/2)
{
for (int j=1;j<=sum/k;j++)
{
col[t1]=i;
t1++;
}
}
else
{
for (int j=1;j<=sum/k;j++)
{
col[t2]=i;
t2++;
}
}
}
t1=1,t2=sum;
int last=1;
for (int i=1;i<=n+1;i++)
{
for (int j=1;j<=n;j++)
{
if (last==1)
{
printf("%d",col[t1]);
if (j!=n) printf(" ");
t1++;
last=2;
}
else
{
printf("%d",col[t2]);
if (j!=n) printf(" ");
t2--;
last=1;
}
}
if (n%2==0) last=3-last;
printf("\n");
}
last=1;
for (int i=1;i<=n+1;i++)
{
for (int j=1;j<=n;j++)
{
if (last==1)
{
printf("%d",col[t1]);
if (j!=n) printf(" ");
t1++;
last=2;
}
else
{
printf("%d",col[t2]);
if (j!=n) printf(" ");
t2--;
last=1;
}
}
if (n%2==0) last=3-last;
printf("\n");
}
}
int main()
{
cin>>T;
while(T--) sol();
return 0;
}
H.Harmony-Pairs
算法标签:数位dp
正好有机会学一下数位dp。
数位dp总结 之 从入门到模板
之前一直望而却步,学了一下感觉其实也不是很难理解,但是做题要能熟练用就是另一回事了。
$dp[pos][del][eqb][eqa]$ pos表示当前的数位,del表示当前a和b数位和之差(避免负数取2500为零点),eqb表示当前B是否取到N的最大值,eqa表示当前A是否取到B的最大值。通过eqb和eqa决定转移时数位取值范围。这样一来最终的状态个数也是很有限的。
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
int digit[20];
int dp[200][5000][2][2];
char n[200];
int dfs(int pos,int del,int eqb,int eqa)
{
if (pos==-1)
{
if (del>2500)
return 1;
else return 0;
}
if (dp[pos][del][eqb][eqa]!=-1) return dp[pos][del][eqb][eqa];
int upb=eqb?n[pos]:9;
int sum=0;
for (int b=0;b<=upb;b++)
{
for (int a=0;a<=(eqa?b:9);a++)
{
sum=(sum+dfs(pos-1,del+a-b,eqb&&(b==n[pos]),eqa&&(a==b)))%MOD;
}
}
dp[pos][del][eqb][eqa]=sum;
return sum;
}
int main()
{
scanf("%s",n);
int len=strlen(n);
reverse(n,n+len);
for (int i=0;i<len;i++) n[i]-='0';
memset(dp,-1,sizeof(dp));
printf("%d",dfs(len-1,2500,1,1));
return 0;
}