A
这道题目是很明显的贪心,因为位数多的数字一定更大,所以我们可以记录前一位数字,通过当前位置的配对,尽量保证和上一位不同
代码
#include<bits/stdc++.h>
using namespace std;
int n;
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
int t;scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
char x;
int dig,last=-1;
getchar();
for(int i=1;i<=n;i++)
{
scanf("%c",&x);
dig=x-'0';
if(dig+1!=last)
{
last=dig+1;
printf("%d",1);
continue;
}
last=dig;
printf("%d",0);
}
printf("\n");
}
return 0;
}
B
这道题目要求至少有四个因子,并且所有的因子的差大于等于d的最小数
首先所有的数都有因子1,所以第二个因子b大于等于d+1,考虑到按从小到大排序因子,所以这里枚举的因子一定是素数,然后第三个因子c大于等于b+d,第四个因子可以是c*b,可以证明b*c-c大于d,所以就可以得到数字为b*c
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+5;
typedef long long ll;
ll n;
int p[maxn];
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
int t;scanf("%d",&t);
for(int i=2;i<=maxn;i++)
if(!p[i])
for(int j=2*i;j<=maxn;j+=i) p[j]=1;
while(t--)
{
scanf("%lld",&n);
int p1,p2;
for(p1=1+n;p[p1];p1++);
for(p2=p1+n;p[p2];p2++);
ll ans=1LL*p1*p2;
printf("%lld\n",ans);
}
return 0;
}
C
这道题目还是有贪心的思想,首先可以将a排序
我们可以证明,每次都一定要取一个最大的数字,否则,这个数字以后将无法被取走,这样我们就可以在已知上一次的较大值时,计算这次是否可以取到,所以这样我们就可以通过枚举第一次取得较小值,然后一直贪心的取
实现的过程中,有一些小的细节:比如判重,由于这个ai的范围较大,不能每次都赋一次值,所以我用了一个map记录
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+5;
const int N=1e6+5;
typedef long long ll;
int n,a[maxn],xx[maxn],yy[maxn];
int tmp[N];
map <int,int> G;
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
int t;scanf("%d",&t);
while(t--)
{
scanf("%d",&n); int maxx=0;
for(int i=1;i<=2*n;i++) scanf("%d",&a[i]),maxx=max(maxx,a[i]);
sort(a+1,a+2*n+1);
for(int i=1;i<=2*n;i++) G[a[i]]++;
int yes=0;
for(int i=1;i<2*n;i++)
{
for(int j=1;j<=2*n;j++) tmp[a[j]]=G[a[j]];
int step=0,last=2*n,pos=2*n-1;
if(pos==i) pos--;
tmp[a[i]]--; tmp[a[2*n]]--;
xx[++step]=a[i]; yy[step]=a[n*2];
while(step<n)
{
int dig=a[last]-a[pos];
tmp[a[pos]]--;
if(!G[dig] || !tmp[dig] || !pos) break;
xx[++step]=a[pos]; yy[step]=dig;
tmp[dig]--;
last=pos;
while(!tmp[a[pos]] && pos>=0) pos--;
}
if(step==n) yes=i;
if(yes) break;
}
if(!yes) printf("NO\n");
else
{
printf("YES\n%d\n",a[yes]+a[2*n]);
for(int i=1;i<=n;i++)
printf("%d %d\n",xx[i],yy[i]);
}
for(int i=1;i<=2*n;i++) G[a[i]]--;
}
return 0;
}
D
这道题目的思路来自于一定要从最左侧的和最右侧开始取,否则它们将会被剩下,然后,我们可以求两个数组,s和p分别表示从左开始取和从右开始取的第i位剩余的个数,这些可以在O(N)的时间内完成
然后我们可以枚举交换的位置i和i+1,验证pi-1,ai,ai+1,si+2,进行验证即可
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int t,n,a[maxn],s[maxn],p[maxn],b[maxn];
int check(int f[],int cnt)
{
int e[maxn];
for(int i=1;i<=cnt;i++) e[i]=f[i];
for(int i=1;i<cnt;i++)
{
if(e[i]>e[i+1]) return 0;
e[i+1]-=e[i];
e[i]=0;
}
if(!e[cnt]) return 1;
return 0;
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
if(n==1) {printf("NO\n"); continue;}
if(check(a,n)==1) { printf("YES\n"); continue;}
swap(a[1],a[2]); if(check(a,n)==1) { printf("YES\n"); continue;}
swap(a[1],a[2]); swap(a[n-1],a[n]); if(check(a,n)==1) { printf("YES\n"); continue;}
swap(a[n-1],a[n]);
p[1]=b[1];
for(int i=2;i<=n;i++)
{
if(p[i-1]==-1 || b[i-1]>b[i])
{
p[i]=-1;
continue;
}
b[i]-=b[i-1];
b[i-1]=0;
p[i]=b[i];
}
for(int i=1;i<=n;i++) b[i]=a[i];
s[n]=b[n];
for(int i=n-1;i>=1;i--)
{
if(s[i+1]==-1 || b[i+1]>b[i])
{
s[i]=-1;
continue;
}
b[i]-=b[i+1];
b[i+1]=0;
s[i]=b[i];
}
int flag=1;
for(int i=2;i+2<=n;i++)
{
int c[5]={0,p[i-1],a[i],a[i+1],s[i+2]};
if(c[1]==-1 || c[4]==-1) continue;
swap(c[2],c[3]);
if(check(c,4)==1) {flag=0; printf("YES\n"); break;}
}
if(flag) printf("NO\n");
}
return 0;
}
E