题目给你蓝,红问你哪种大的更多一些?首先我们比较大小肯定会考虑最高位,然后考虑次高位,但是这些又有什么用呢,直接比较蓝红的数量就行了.
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+500;
int w[N];
char s1[N],s2[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
scanf("%s",s1+1);
scanf("%s",s2+1);
int num1=0,num2=0;
for(int i=1;i<=n;i++)
{
if(s1[i]>s2[i]) num1++;
else if(s1[i]<s2[i]) num2++;
}
if(num1>num2) puts("RED");
else if(num1==num2) puts("EQUAL");
else puts("BLUE");
}
return 0;
}
考虑合法的情况,就是按题意说的,每次你选择一次上下,下次只能选择左右,你选择一次左右,那么下次只能选择左右.所以可知上下的数量和左右数量的绝对值不会超过1,所以我们就知道,假如给你次操作,左右的操作和是
的,上下的操作和为
的,那么我们不妨枚举左的操作次数,和上的操作次数,这样,右的操作次数和下的操作次数就已知了.如此
即可解决此问题,我们这里为了简单,用set记录点的数量.
#include <bits/stdc++.h>
using namespace std;
set<pair<int,int> >ans;
int main()
{
int n;cin>>n;
int x=n/2,y=n-x;
for(int i=0;i<=x;i++)//上
{
for(int j=0;j<=y;j++)//右
{
int down=(x-i);int left=(y-j);
ans.insert({j-left,i-down});
}
}swap(x,y);
for(int i=0;i<=x;i++)//上
{
for(int j=0;j<=y;j++)//右
{
int down=(x-i);int left=(y-j);
ans.insert({j-left,i-down});
}
}cout<<ans.size()<<endl;
return 0;
}
考虑gcd的辗转相除法公式有,如此推至n项即是
然后我们每次都是给区间加上一个确定的数,我们可以观察2-n项会发现,他们的gcd是不变的,我们可以求出2-n项的gcd,然后每次改变的值即可求得答案了,注意相减是有负数产生排序一下即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll a[N];
int main()
{
ll ans=0;
ll n,m;
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
sort(a+1,a+1+n);
for(int i=2;i<=n;i++) ans=__gcd(ans,a[i]-a[i-1]);
while(m--)
{
ll x;
scanf("%lld",&x);
printf("%lld ",__gcd(ans,a[1]+x));
}puts("");
return 0;
}
考虑dp,令表示.到了第i个,选了j个,填了多少容量.一个很显然的想法是拿背包写,没错,就是背包,你拿背包填就完事,最后的价值是不可能超过容量的2倍的,因为我扩大了1倍.也就是不会超过容量的一倍的.
#include <bits/stdc++.h>
using namespace std;
const int N=105;
int a[N],b[N];
int f[N][N][N*N];//到了第i个,选了j个,填了多少容量.
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i],&b[i]);
}int sum=0;
memset(f,-0x3f,sizeof(f)),f[0][0][0]=0;
for(int i=1;i<=n;i++)
{
sum+=a[i];
for(int j=0;j<=i;j++)
{
for(int k=0;k<=sum;k++)
{
if(j&&k>=a[i]) f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k-a[i]]+2*b[i]);
f[i][j][k]=max(f[i][j][k],f[i-1][j][k]+b[i]);
}
}
}
for(int i=1;i<=n;i++)
{
int ans=0;
for(int j=0;j<=sum;j++)
{
ans=max(ans,min(2*j,f[n][i][j]));
}
printf("%.10f ",(double)ans/(2.0));
}puts("");
return 0;
}
这题了解下I,C的操作就挺简单的了.然后就是开个x[]数组记录下偏移值.
#include <bits/stdc++.h>
using namespace std;
const int N=1005,M=3;
int a[N*N][M];
int ans[N][N];
int p[3],x[3];//置换后的id,i,j,k的增值.
char s[N*N];
int n,m;
void del(int &u)
{
u--;if(u<0) u+=n;
}
void add(int &u)
{
u++;if(u>=n) u-=n;
}
void solve()
{
for(int i=0;i<3;i++) x[i]=0,p[i]=i;
for(int i=1;i<=m;i++)
{
if(s[i]=='R') add(x[p[1]]);
if(s[i]=='L') del(x[p[1]]);
if(s[i]=='D') add(x[p[0]]);
if(s[i]=='U') del(x[p[0]]);
if(s[i]=='I') swap(p[1],p[2]);
if(s[i]=='C') swap(p[0],p[2]);
}
for(int i=1;i<=n*n;i++)
{
for(int j=0;j<3;j++)
{
a[i][j]=(a[i][j]+x[j]-1)%n+1;
}ans[a[i][p[0]]][a[i][p[1]]]=a[i][p[2]];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%d ",ans[i][j]);
}puts("");
}
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&a[(i-1)*n+j][2]);
a[(i-1)*n+j][0]=i;a[(i-1)*n+j][1]=j;
}
scanf("%s",s+1);
solve();
}
return 0;
}
这题你把题目给定的01串转化成图,我们对于表示
建图,反之
,它给定的操作其实就是告诉你,它是个无向图.然后我们尽量往前走就ok,注意要走完n步.难点在于想到转化.
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+500;
char s[N];
int ep[N];//记录i->i+1有几条边.
void solve()
{
scanf("%s",s+1);int n=strlen(s+1);int id=n;
for(int i=1;i<=n;i++)//一共会运行n次.
{
if(s[i]-'0') ep[id++]++;
else ep[--id]++;
}id=n;
for(int i=1;i<=n;i++)
{
if(ep[id-1]&&(!ep[id]||ep[id-1]>1))
{
ep[--id]--;
printf("0");
}
else
{
ep[id++]--;
printf("1");
}
}puts("");
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
solve();
return 0;
}
京公网安备 11010502036488号