昨晚的Code Forces,还在div2混。。。不过A了4题,加了近200分,直接变紫色了:),下一场就是div1了。
题目总体并不难,下面简单总结一下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int d[111];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",d+i);
sort(d,d+n);
for(int i=0;i<n;i++)
printf("%d ", d[i]);
puts("");
}
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
char str[10000];
int main()
{
int n;
scanf("%d",&n);
scanf("%s",str);
int len = strlen(str);
int lpos = -1;
int rpos = -1;
int ans=0;
int find = 0;
for(int i=0; i<len; i++)
{
if(str[i]=='L')
{
lpos=i;
if(find==0)
{
find = 2;
}
else if(find==1)
{
if((lpos-rpos)%2==0) ans++;
find=2;
}
}
if(str[i]=='R')
{
rpos=i;
if(find==0)
{
ans+=i;
find=1;
}
else if(find==2)
{
ans+=rpos-lpos-1;
find=1;
}
}
}
if(rpos<lpos)
ans+=n-1-lpos;
else if(rpos==lpos && lpos==-1)
ans=n;
printf("%d\n", ans);
}
a,b,c,
d,e,f,
g,h,i.
那么所求的值就是aa+bd+cg+db+ee+fh+gc+hf+ii。出现两次的不论是0还是1都会等于0,所以式子就是aa+ee+ii。反转任意行或者一列都会使值改变。代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int main()
{
int n;
scanf("%d",&n);
int ans=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
int tmp;
scanf("%d",&tmp);
if(i==j)
ans^=tmp;
}
}
int m;
scanf("%d",&m);
while(m--)
{
int op;
scanf("%d",&op);
if(op==3)
{
printf("%d",ans);
}
else
{
int tmp;
scanf("%d",&tmp);
ans = 1-ans;
}
}
puts("");
}
0 1 2 3 4 5 6 7,y选择这些值时实际的数值为:
7 6 5 4 3 2 1 0。
通过这个图,我们可以猜测出:如果x选择了2,那么y可以选择对称位置的2。如果x同时选择了2和对称位置的5,那么y可以选择没有被使用的对称对,比如0和7。
虽然没有证明,但是感觉是对的。代码也过了:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int d[1000010];
int num[1000010];
int main()
{
int n;
scanf("%d", &n);
int maxn=1000000;
for(int i=0;i<n;i++)
{
int tmp;
scanf("%d",&tmp);
d[tmp] = 1;
}
int pair=0;
int half=1000000/2;
int ans=0;
for(int i=1;i<=half;i++)
{
if(d[i]==true && d[maxn-i+1]==true)
{
pair++;
}
else if(d[i])
{
num[ans++] = maxn-i+1;
d[maxn-i+1] = 2;
}
else if(d[maxn-i+1])
{
num[ans++] = i;
d[i] = 2;
}
}
for(int i=1;i<=half;i++) if(d[i]==0 && d[maxn-i+1]==0)
{
if(pair==0) break;
num[ans++] = i;
num[ans++] = maxn-i+1;
pair--;
}
printf("%d\n", ans);
for(int i=0;i<ans;i++)
printf("%d ",num[i]);
puts("");
}
E题……没什么思路,所以看了一下大牛的代码 = =||。
当边数为奇数时,肯定是不行的。但是当边数为偶数时,就一定是可行的。怎么证明呢?简单来说,任意取一个点,取走该点上的偶数个边。如果该点的度数是偶数,那么取走这个点,剩下的图仍然是一个总边数为偶数边的图;如果度数是奇数,那么最后一条边不取,取该边连接的点为下一个取边的点,重复操作。因为总边数是偶数,所以最后一个取边点一定时偶数,而且刚好取完。
知道思路,代码就很容易了:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100010;
int first[maxn],nxt[maxn<<1],vv[maxn<<1];
bool vis[maxn];
int mark[maxn];
int edge[maxn];
void dfs(int n,int fa)
{
vis[n] = true;
for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && !vis[vv[e]])
dfs(vv[e], n);
int top=0;
for(int e=first[n];e;e=nxt[e]) if(vv[e]!=fa && mark[vv[e]]!=1)
edge[top++]=vv[e]; // 记录可用点
if(top&1)
edge[top++]=fa,mark[n]=1; // 用到当前点到父亲的边,当前点以后不可用
else
mark[n]=2; // 不用到父亲的边,当前点还可以使用一次
for(int i=0; i<top; i+=2)
{
printf("%d %d %d\n", edge[i], n, edge[i+1]);
if(mark[edge[i]]==2) mark[edge[i]]=1;
if(mark[edge[i+1]]==2) mark[edge[i+1]]=1;
}
}
int main()
{
int e=2;
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
nxt[e]=first[u],vv[e]=v,first[u]=e++;
nxt[e]=first[v],vv[e]=u,first[v]=e++;
}
if(m&1)
puts("No solution");
else
dfs(1,0);
}
昨晚的收获就是比赛应该胆大心细,提交之前,好好检查一下题目。变紫没那么难,但是保持紫就有难度了。