AtCoder Regular Contest 149
A
发现所有数字都相同的数一共只有 \(10^6\) 种,考虑枚举每种情况,关键在于如何判断一个数 \(\bmod m\) 是否为 \(0\)。
考虑 \(9\bmod 8=1\),而 \(99\bmod 8=(9\times10+9)\bmod 8=(10\times(9\bmod 8)+(9\bmod 8))\bmod 8=11\bmod 8=3\)
可以递推。
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,m,num,len;
signed main()
{
cin>>n>>m;
for(int i=1;i<=9;++i)
{
int tim=10,p=i%m;
if(p==0)if(len<=1)len=1,num=i;
for(int j=2;j<=n;++j)
{
p=(p+i*tim)%m;
if(p==0)if(len<=j)len=j,num=i;
tim=tim*10%m;
}
}
if(len==0)cout<<-1;
else for(int i=1;i<=len;++i)cout<<num;
return 0;
}
B
比较 adhoc,结论:将一个数组从小到大排序,此时两个数组的 \(LIS\) 的和即为答案。
感性证明:考虑将数组重排,让第一个数组有序至少能让答案增大 \(1\),在不能两个数组同时保证的情况下一定不劣。
答案即为 \(N+LIS(B)\),\(LIS\) 可以在 \(\mathcal O(n\log n)\) 的时间内求出。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N=3e5+5;
struct node{int a,b;}num[N];
int n,b[N];
bool cmp(node q,node w){return q.a<w.a;}
int lowbit(int x){return x&-x;}
void add(int x,int k){while(x<=n)b[x]=max(b[x],k),x+=lowbit(x);}
int query(int x){int res=0;while(x)res=max(res,b[x]),x-=lowbit(x);return res;}
signed main()
{
cin>>n;
for(int i=1;i<=n;++i)cin>>num[i].a;
for(int i=1;i<=n;++i)cin>>num[i].b;
sort(num+1,num+n+1,cmp);
int ans=0;
for(int i=1;i<=n;++i)
{
int f=query(num[i].b)+1;
ans=max(ans,f);add(num[i].b,f);
}
cout<<n+ans;
return 0;
}
C
小清新构造。
让相邻两个的和不为质数,最简单的方法就是让和为偶数,容易知道 奇数+奇数=偶数,偶数+偶数=偶数,所以可以想到把奇数排在上面,偶数排在下面,尽可能减少奇数与偶数的接触。
下面,我们分类讨论 \(n\) 为奇数和偶数的情况。
\(n\) 为偶数
奇数都排在上面 \(n/2\) 行,偶数排在下面 \(n/2\) 行。但是,还有一个问题,第 \(n/2\) 行的数和第 \(n/2+1\) 行的数的和是奇数,可能会出现质数。
考虑如何构造,不难发现如果 \(n/2+1\) 行的数是 \(n/2\) 行的数的倍数,他们的和一定是合数,所以可以构造 \(n/2+1\) 行的数等于 \(n/2\) 行的数的二倍。剩下的数瞎填就好了。
| 3 | 5 | 7 | 9 | 11 | 13 |
| 6 | 10 | 14 | 18 | 22 | 26 |
\(n\) 为奇数
还像偶数一样,把奇数排在上面,偶数排在下面。
但是有一个问题(如下图,\(5\times5\) 的格),\((3,4)\) 的偶数同时与 \((3,3),(2,4)\) 两个奇数相邻,\((3,3)\) 的奇数也同时与两个偶数相邻,我们构造 \(3,6,9,12\) 就可以了。
| \(\color{red}{9}\) | ||||
| \(\color{red}{3}\) | \(\color{blue}{6}\) | |||
| \(\color{blue}{12}\) | ||||
剩下的位置继续构造 \(2\) 倍关系就可以了。
| 9 | 11 | |||
| 5 | 7 | 3 | 6 | 22 |
| 10 | 14 | 12 | ||
Corner Case
当然,\(n=3\) 和 \(n=4\) 的情况需要特殊构造,具体构造方案见代码。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N=1005;
int n,a[N][N],used[N*N];
signed main()
{
cin>>n;
if(n==3){cout<<"5 9 1\n3 7 8\n6 2 4";return 0;}
if(n==4){cout<<"9 11 13 15\n1 3 5 7\n8 6 10 14\n2 4 12 16";return 0;}
if(n%2==0)
{
for(int i=1;i<=n;++i)
{
a[n/2][i]=i+i+1;
a[n/2+1][i]=a[n/2][i]*2;
used[i+i+1]=1;used[4*i+2]=1;
}
int now=1;
for(int i=1;i<=n/2-1;++i)
for(int j=1;j<=n;++j)
{
while(used[now])now+=2;
a[i][j]=now;now+=2;
}
now=2;
for(int i=n/2+2;i<=n;++i)
for(int j=1;j<=n;++j)
{
while(used[now])now+=2;
a[i][j]=now;now+=2;
}
}
else
{
a[n/2+1][n/2+1]=3;used[3]=1;
a[n/2+1][n/2+2]=6;used[6]=1;
a[n/2][n/2+2]=9;used[9]=1;
a[n/2+2][n/2+1]=12;used[12]=1;
int now=5;
for(int i=1;i<=n/2;++i)
{
while(used[now])now+=2;
a[n/2+1][i]=now;a[n/2+2][i]=now*2;
used[now]=1;used[now*2]=1;now+=2;
}
for(int i=n/2+3;i<=n;++i)
{
while(used[now])now+=2;
a[n/2][i]=now;a[n/2+1][i]=now*2;
used[now]=1;used[now*2]=1;now+=2;
}
now=1;
for(int i=1;i<=n/2;++i)
for(int j=1;j<=n;++j)
{
if(a[i][j])continue;
while(used[now])now+=2;
a[i][j]=now;now+=2;
}
now=2;
for(int i=n/2+2;i<=n;++i)
for(int j=1;j<=n;++j)
{
if(a[i][j])continue;
while(used[now])now+=2;
a[i][j]=now;now+=2;
}
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
cout<<a[i][j]<<" ";
cout<<endl;
}
return 0;
}

浙公网安备 33010602011771号