A. Madoka and Math Dad
样例输入:
5
1
2
3
4
5
样例输出:
1
2
21
121
212
题意:给定一个n,构造一个十进制数,使得每一位的值都是正的而且相邻两位不能相同,各位数字之和为n,问这个十进制整数最大是多少?
分析:首先我们能够发现制约一个数的最重要因素是数的位数,其次才是最高位的值,为了使得我们构造的位数尽量多,我们应该用1和2来进行构造,也就是根据n对3取余的结果分类讨论一下即可。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int N=2e5+10;
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
scanf("%d",&n);
if(n%3==1)
{
printf("1");
for(int i=1;i*3<=n;i++)
printf("21");
}
else if(n%3==2)
{
printf("2");
for(int i=1;i*3<=n;i++)
printf("12");
}
else
{
for(int i=1;i*3<=n;i++)
printf("21");
}
puts("");
}
return 0;
}
B. Madoka and the Elegant Gift
样例输入:
5
3 3
100
011
011
3 3
110
111
110
1 5
01111
4 5
11111
01010
01000
01000
3 2
11
00
11
样例输出:
YES
NO
YES
NO
YES
题意:给定一个01矩阵,问是不是所有的全1矩阵都是不重叠的。
分析:通过简单分析可以发现,只要保证2*2的矩阵里面不是3个1即可
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int N=2e2+10;
char s[N][N];
int f[N][N];
int main()
{
int T;
cin>>T;
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
memset(f,0,sizeof f);
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]+1);
for(int j=1;j<=m;j++)
{
if(s[i][j]=='1')
f[i][j]=1;
else
f[i][j]=0;
f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
}
}
bool flag=true;
for(int i=1;i+1<=n;i++)
for(int j=1;j+1<=m;j++)
if(f[i+1][j+1]-f[i-1][j+1]-f[i+1][j-1]+f[i-1][j-1]==3)
{
flag=false;
break;
}
if(flag) puts("YES");
else puts("NO");
}
return 0;
}
C. Madoka and Childish Pranks
样例输入:
4
4 5
01000
10100
01010
00110
2 3
001
010
3 3
110
101
000
1 1
0
样例输出:
4
1 1 3 3
3 3 4 4
4 3 4 4
4 2 4 3
1
1 2 2 3
-1
0
题意:给定一个01矩阵代表我们最终要构造的矩阵,一开始我们有一个初始矩阵为全0矩阵,然后我们每次可以选择一个子矩阵,对这个子矩阵操作后的结果就是左上角的位置变为0,距离左上角位置为奇数的位置变为1,距离为偶数的位置变为0.问能否通过有限次操作使得矩阵变为我们要构造的矩阵。
分析:这里可以选择采用1*2和2*1的矩阵进行构造,对于每一行,我们从后往前考虑,如果当前位置为1,那么我们就选择当前位置和当前位置左面一个位置进行一次操作,最后我们可以把除了第一列之外的矩阵全部操作完成,然后我们从第n行往上操作第1列矩阵,如果当前位置为1,那么我们就选择当前位置和上面一个位置进行一次操作,可以发现,只有当第一行第一列的空格是1时不合法,其他矩阵都是可以按照这种方法构造的。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int N=2e2+10,M=1e4+10;
char s[N][N];
int x1[M],y1[M],x2[M],y2[M];
int main()
{
int T;
cin>>T;
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
int tt=0;
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]+1);
for(int j=m;j>=2;j--)
if(s[i][j]=='1')
x1[++tt]=i,y1[tt]=j-1,x2[tt]=i,y2[tt]=j;
}
if(s[1][1]=='1') puts("-1");
else
{
for(int i=n;i>1;i--)
if(s[i][1]=='1')
x1[++tt]=i-1,y1[tt]=1,x2[tt]=i,y2[tt]=1;
printf("%d\n",tt);
for(int i=1;i<=tt;i++)
printf("%d %d %d %d\n",x1[i],y1[i],x2[i],y2[i]);
}
}
return 0;
}
D. Madoka and the Best School in Russia
样例输入:
8
6 2
12 2
36 2
8 2
1000 10
2376 6
128 4
16384 4
样例输出:
NO
NO
YES
NO
YES
YES
NO
YES
题意:给定一个n,定义一个数x为good当且仅当n是d的倍数,定义一个数是beautiful当且仅当这个数是一个good数且不能表示成两个good数的乘积。现在给你一个x,问你能不能将这个数表示成若干个beautiful的乘积,如果能找出两种及以上的表示形式就输出YES,否则输出NO
分析:我们先来看一下beautiful数具备什么特征,首先其是一个good数就说明其含有一个因子d,但是由于其不能表示成两个gooc数的乘积,所以这个数里面至多含有一个因子d,不可能含有因子d*d,因为一旦含有d*d,那么一定可以被表示为两个good数的乘积。那么我们的目的就转变为将x表示成若干个数的乘积,其中每个数都只能含有一个因子d,其他因子无所谓,那么我们就可以按照下面的方法进行分类讨论:
我们先让x一直除以d,用cnt记录x含有d因子的幂次,最后x中就不再含有因子d,这个时候我们先来看一下cnt的情况,如果cnt<2,那么显然不能分成多个beautiful数的乘积直接输出NO,那么剩下的情况都是cnt>=2的情况,如果x是一个合数,不妨设x=a*b,那么我们显然就至少有两种划分方式:
x*d d ……,或者a*d b*d ……。那么对于x是合数的情况我们直接输出YES即可
下面就是x是质数的情况:
这个时候一种表示形式就是
x*d d ……。
接下来我们还需要找到另一种表示形式
因为x是一个质数,所以x肯定是已经没办法进行分解了,这个时候我们应该分解d
第一种情况:d是一个质数,那么d也无法分解,我们直接输出NO即可
第二种情况:d不止含有一个质因子,以k个质因子为例,假设是d=(p1^a1)*(p2^a2)*……*(pk^ak)
这个时候我们找一个质因子pi使得满足x*pi^ai不含有因子d,那么我们就可以把x*d分解为x*pi^ai和(p1^a1)*(p2^a2)*……(pi-1^ai-1)*(pi+1^ai+1)*……*(pk^ak),我们把这两个数分别作为两个d的系数即可,这样我们就找到了另外一种构造方式
最后一种情况就是d只含有一个质因子,不妨假设d=u^k,这个时候我们要将d分为(u^p)*(u^q),p+q=k,这个时候我们将两者其中一个和x相乘作为一个数(这个数不能含有因子d),另一个数作为第二个数即可构造出第二种形式,但是需要注意的一点是,当k等于2时,p和q都等于1,这个时候如果x等于u那么我们是没办法构造成功的,注意一下这种形式的特判即可。
细节见代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int N=2e5+10;
vector<int>p;
vector<int>t;
int main()
{
int T;
cin>>T;
while(T--)
{
int x,d;
scanf("%d%d",&x,&d);
int cnt=0;//记录x中含有d的幂次
while(x%d==0)
{
x/=d;
cnt++;
}
bool flag=true;
for(int i=2;i*i<=x;i++)
if(x%i==0)
{
flag=false;
break;
}
if(cnt<2) puts("NO");
else if(!flag) puts("YES");
else//剩余因子x是一个质数
{
p.clear();
t.clear();
int td=d;
for(int i=2;i*i<=d;i++)
{
if(td%i==0)
{
p.push_back(i);
int tt=0;
while(td%i==0)
{
tt++;
td/=i;
}
t.push_back(tt);
}
}
if(td!=1) p.push_back(td),t.push_back(1);
if(p.size()==1)//d只含有一个质因子
{
if(t[0]==1)//d是一个质数
puts("NO");
else
{
if(cnt==2) puts("NO");
else if(d==x*x&&cnt==3) puts("NO");
else puts("YES");
}
}
else
{
if(cnt==2) puts("NO");
else puts("YES");
}
}
}
return 0;
}