A题。。。水题。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll __int64
using namespace std;
int main()
{
ll n;
while(scanf("%I64d",&n)==1)
{
if(n&1)
{
ll ans=(ll)n/(ll)2-n;
printf("%I64d\n",ans);
}
else
{
ll ans=(ll)n/(ll)2;
printf("%I64d\n",ans);
}
}
return 0;
}
B题。。。个人觉得要点想法。。。本人FST了,写法出了点问题,有一种情况无法判断(第31组数据。。)。。。
先把答案矩阵(A矩阵)全部置为1,然后看B矩阵,如果这个点是0,就把这一行一列都置成0,然后统计答案矩阵行列1的个数,最后看B矩阵,如果B矩阵上一个位置是1,那么这一行或一列最少要有一个1,如果没有就是NO了。。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=110;
int mp[MAXN][MAXN];
int row[MAXN],col[MAXN];
int ans[MAXN][MAXN];
int main()
{
int n,m,i,j,k;
while(scanf("%d%d",&n,&m)==2)
{
memset(row,0,sizeof(row));
memset(col,0,sizeof(col));
for(i=0;i<n;i++)
for(j=0;j<m;j++)
ans[i][j]=1;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",&mp[i][j]);
if(!mp[i][j])
{
for(k=0;k<n;k++)
ans[k][j]=0;
for(k=0;k<m;k++)
ans[i][k]=0;
}
}
}
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
row[i]+=ans[i][j];
col[j]+=ans[i][j];
}
int flag=1;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(mp[i][j]&&!ans[i][j])
{
if(row[i]==0&&col[j]==0)
{
flag=0;
break;
}
}
}
}
if(!flag)
{
printf("NO\n");
continue; }
printf("YES\n");
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
printf("%d ",ans[i][j]);
printf("\n");
}
}
return 0;
}
C题
首先,按上下的次数是一定的,还有就是光标在左边就只要改变左边就好,在右边只要改变右边就好,比如abcdcbz,可以把a变成z花1步,把z变成a也是花一步,边其中一个就可以,所以直接模拟就是。。而且光标只要在其中一半移动就行。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=100010;
char str[MAXN];
int cnt[MAXN];
int main()
{
int n,p,i,j;
while(scanf("%d%d",&n,&p)==2)
{
scanf("%s",str+1);
int ans=0;
int l=MAXN+1;
int r=-1;
memset(cnt,0,sizeof(cnt));
for(i=1;i<=n/2;i++)
{
cnt[i]=abs(str[i]-str[n-i+1]);
if(cnt[i])
{
l=min(l,i);
r=max(r,i);
}
if(cnt[i]>13)
cnt[i]=26-cnt[i];
ans+=cnt[i];
}
if(l==MAXN+1)
{
printf("%d\n",ans);
continue;
}
if(n&1)
{
int mid=n/2+1;
if(p<mid)
{
if(p>=r)
ans+=p-l;
else if(p<=l)
ans+=r-p;
else
{
int temp1=r-p;
int temp2=p-l;
int temp=min(temp1,temp2);
ans+=temp+r-l;;
}
}
else if(p>mid)
{
l=n-l+1;
r=n-r+1;
swap(l,r);
if(p>=r)
ans+=p-l;
else if(p<=l)
ans+=r-p;
else
{
int temp1=r-p;
int temp2=p-l;
int temp=min(temp1,temp2);
ans+=temp+r-l;;
}
}
else
{
ans+=mid-l;
}
}
else
{
int mid=n/2;
if(p<=mid)
{
if(p>=r)
ans+=p-l;
else if(p<=l)
ans+=r-p;
else
{
int temp1=r-p;
int temp2=p-l;
int temp=min(temp1,temp2);
ans+=temp+r-l;;
}
}
else
{
l=n-l+1;
r=n-r+1;
swap(l,r);
if(p>=r)
ans+=p-l;
else if(p<=l)
ans+=r-p;
else
{
int temp1=r-p;
int temp2=p-l;
int temp=min(temp1,temp2);
ans+=temp+r-l;;
}
}
}
printf("%d\n",ans);
}
return 0;
}
/*
7 4
abcdcba
7 4
azcdcba
7 6
azcdcba
7 5
azcdcba
6 3
abzcba
6 6
abzcba
6 1
abczbb
*/
D题
比赛时不会的题。。
就是以每个点为根,遍历生成一棵树,根节点的权值必须不小于其他的点,而且根节点和其他点的差值不大于d,暴力统计个数就行。。
权值相同的点可能会有重复,所以加一个标记,当权值相等时看有没有这个标记。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll __int64
using namespace std;
const int MAXN=2010;
const int MOD=1e9+7;
struct EDGE
{
int v,next;
}edge[MAXN<<1];
int head[MAXN],size;
bool vis[MAXN];
void init()
{
memset(head,-1,sizeof(head));
size=0;
}
void add_edge(int u,int v)
{
edge[size].v=v;
edge[size].next=head[u];
head[u]=size++;
}
int val[MAXN];
int d,n;
ll dfs(int u,int fa,int c)
{
int i;
ll sum=1;
for(i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(val[v]>c)
continue;
if(v==fa)
continue;
if(c-val[v]>d)
continue;
if(val[v]==c&&vis[v])
continue;
sum=sum*dfs(v,u,c)%MOD;
}
return sum+1;
}
int main()
{
int i;
while(scanf("%d%d",&d,&n)==2)
{
for(i=1;i<=n;i++)
scanf("%d",&val[i]);
int u,v;
init();
for(i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
memset(vis,0,sizeof(vis));
ll ans=0;
for(i=1;i<=n;i++)
{
ans--;
ans=(ans+dfs(i,-1,val[i]))%MOD;
vis[i]=1;
}
printf("%I64d\n",ans);
}
return 0;
}