最近真是智商爆炸,掉下div1也是理所当然的吧,是不是水刷多了啊?
下面是题解
A
http://codeforces.com/contest/233/problem/A
题意:给一个n,构建一个n的排列,使得两次迭代返回本身,不可能则输出-1。
做法:奇数输出-1,偶数把奇偶位互换即可。
代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
scanf("%d", &n);
if(n&1)printf("-1\n");
else{
for(int i=1;i<=n;i++){
if(i&1)printf("%d ", i+1);
else printf("%d%c", i-1, i==n?'\n':' ');
}
}
}
B
http://codeforces.com/contest/233/problem/B
题意:给一个正整数n,n<=1e18,求方程
x2 + s(x)⋅x − n = 0
的正整数根。其中s(x)是x的各位和。
做法:显然s(x)不会很大,粗略地记为s(x)<=200(范围显然可以更小);那这样就有
x2<x2+s(x)⋅x=n<x2+200x+10000−10000=(x+100)2−10000
,
整理一下得
n+10000−−−−−−−−√−100<x<n√
,显然这个范围的数不超过100个,那么逐个验证就OK了。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll s(ll x){
ll ans=0;
while(x){
ans+=x%10;
x/=10;
}
return ans;
}
int main()
{
ll n;
scanf("%I64d", &n);
ll l=(ll)(sqrt(n+10000)-100);
if(l<0)l=0;
ll r=sqrt(n)+1;
for(ll i=l;i<=r;i++){
if(i*i+i*s(i)==n){
printf("%I64d\n", i);
return 0;
}
}
printf("-1\n");
}
C
http://codeforces.com/contest/233/problem/C
题意:给一个n,n<=1e5,构造一个100点以内的图,使得图内的三角形正好是n个。
做法:显然100点的完全图是超过1e5个三元组的,那么,我们找到最大的一个siz,使得C(siz,3)<=n,这样这个有siz个点的完全图就用掉了C(siz,3)个三元组,n-=C(siz,3)。然后依次添加点,每个点找到最大的一个num,使得C(num,2)<=n,这样从这个点往完全图连num条线,就用掉了C(num,2)个三元组,n-=C(num,2),一直这样加点直到n是0。实际上这样拆分好像正好能卡过极限数据吧,因为序列是n方级别,所以其实不太好宽松的证明,不过实在不行跑一遍全数据也不是不可以。
代码:
#include <bits/stdc++.h>
using namespace std;
int ans[105];
int g[105][105];
int tot;
int main()
{
memset(g, 0, sizeof(g));
int n;
scanf("%d", &n);
int siz;
for(int i=3;i<=100;i++){
if(i*(i-1)*(i-2)/6>n){
siz=i-1;
break;
}
}
n-=siz*(siz-1)*(siz-2)/6;
tot=0;
while(n){
int tag;
for(int i=2;i<=100;i++){
if(i*(i-1)/2>n){
tag=i-1;
break;
}
}
ans[++tot]=tag;
n-=tag*(tag-1)/2;
}
for(int i=1;i<=siz;i++)for(int j=1;j<=siz;j++)g[i][j]=1;
for(int i=1;i<=tot;i++)for(int j=1;j<=ans[i];j++)g[siz+i][j]=g[j][siz+i]=1;
for(int i=1;i<=siz+tot;i++)g[i][i]=0;
printf("%d\n", siz+tot);
for(int i=1;i<=siz+tot;i++){
for(int j=1;j<=siz+tot;j++){
printf("%d", g[i][j]);
}
printf("\n");
}
}