NOWL #50

最近真是智商爆炸,掉下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)xn=0 的正整数根。其中s(x)是x的各位和。
做法:显然s(x)不会很大,粗略地记为s(x)<=200(范围显然可以更小);那这样就有 x2<x2+s(x)x=n<x2+200x+1000010000=(x+100)210000 ,
整理一下得 n+10000100<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");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值