SRM 622 div1

              好久没写博客了,最近状况不太好,有些力不从心,不知道还能走多远,留给自己的时间不多了……正好今天打了场tc,就发个题解吧……


250  floyd+枚举

      这个题大概的意思就是给出一个完全图,每个点要从这个点出发到所有其他的点,并且只沿最短路走,如果有多条,那么就随机走。问题是求所有有向边有可能使用的此时大于等于T的边权和。n比较小,可以先用floyd求下最短路,然后枚举一下起点和终点,然后枚举边,判断当前边是否在最短路中。


代码:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=55;
class BuildingRoutes
{
    public:
    int g[maxn][maxn],used[maxn][maxn],n;
    int d[maxn][maxn];
    bool inq[maxn];
    void floyd()
    {
        for(int i=0;i<n;++i)
            for(int j=0;j<n;++j)
                d[i][j]=g[i][j];
        for(int k=0;k<n;++k)
            for(int i=0;i<n;++i)
                for(int j=0;j<n;++j)
                    d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
        for(int s=0;s<n;++s)
            for(int t=0;t<n;++t)
            {
                if(s==t) continue;
                for(int i=0;i<n;++i)
                    for(int j=0;j<n;++j)
                        if(d[s][i]+g[i][j]+d[j][t]==d[s][t])
                            used[i][j]++;
            }
    }
    int build(vector <string> dist, int T)
    {
        n=dist.size();
        for(int i=0;i<n;++i)
            for(int j=0;j<n;++j)
                g[i][j]=dist[i][j]-'0';
        memset(used,0,sizeof(used));
        floyd();
        int ans=0;
        for(int i=0;i<n;++i)
            for(int j=0;j<n;++j)
                if(used[i][j]>=T)
                    ans+=g[i][j];
        return ans;
    }
};

500  贪心

         给出一棵树,要求去掉一些边,将树分成尽可能少的树,并且新的树是原来的树的子树,任意两点之间的距离小于MaxDis。第一题浪费了好多时间,导致这题没弄完,其实很简单,对于一个结点来说,我们首先去掉那些距离这个点的最大距离大于MaxDis的子树,然后对于所有的子树,排序后,贪心从大到小删,直到任意两个点子树之间没有大于MaxDis的两个结点。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=55;
class Ethernet
{
    public:
    vector<pair<int,int> >g[maxn];
    int maxd[maxn],val[maxn],n,mxd;
    void dfs(int u)
    {
        maxd[u]=0;val[u]=0;
        int cnt=0;
        vector<int>num;
        for(int i=0;i<(int)g[u].size();++i)
        {
            int v=g[u][i].first;
            dfs(v);
            val[u]+=val[v];
            num.push_back(maxd[v]+g[u][i].second);
        }
        sort(num.begin(),num.end());
        cnt=num.size();
        while(cnt>0&&num[cnt-1]>mxd) val[u]++,cnt--;
        while(cnt>1&&num[cnt-1]+num[cnt-2]>mxd) val[u]++,cnt--;
        if(cnt) maxd[u]=num[cnt-1];
    }
    int connect(vector <int> parent, vector <int> dist, int maxDist)
    {
        n=parent.size()+1;
        for(int i=0;i<n;++i) g[i].clear();
        mxd=maxDist;
        for(int i=0;i<n-1;++i)
        {
            g[parent[i]].push_back(make_pair(i+1,dist[i]));
        }
        dfs(0);
        return val[0]+1;
    }
};

900 记忆化搜索

         给出两个数A,B,求区间[A,B]中的数转化为“斐波那契进制数”再转化为二进制数以后的异或和。把前几项值列出来大概就能看出来了,比如12(010101),第一个比它小的是斐波那契数是8(010000),它们之间的数的值恰好和(1~4)相对应,只是多了个最高位,那么用map记录一下值,然后计算一下就好了,由于每次会减掉一个斐波那契数,所以要访问的值不会很多。位数可能比较大,用了bitset,比较方便~


代码:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<bitset>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
typedef bitset<72> bt;
const int mod=1000000007;
class FibonacciXor
{
    public:
    ll f[110];
    map<ll,bt>mp;
    bt Xor(bt a,bt b)
    {
        bt c;
        for(int i=0;i<72;++i)
            c[i]=(a[i]!=b[i]);
        return c;
    }
    void Init()
    {
        f[0]=1;f[1]=2;
        for(int i=2;i<72;++i)
            f[i]=f[i-1]+f[i-2];
        mp.clear();
    }
    bt cal(ll x)
    {
        if(x==1) return bt(1);
        if(x==0) return bt(0);
        if(mp.find(x)!=mp.end()) return mp[x];
        bt msk;
        int i=71;
        for(;i>=0;--i)
        {
            if(f[i]<=x)
                break;
        }
        if(x==f[i])
        {
            msk[i]=1;
            return mp[x]=Xor(msk,cal(x-1));
        }
        ll y=(x-f[i]);
        if(y&1) msk[i]=1;
        msk=Xor(msk,cal(y));
        msk=Xor(msk,cal(f[i]));
        return mp[x]=msk;
    }
    int find(long long A, long long B)
    {
        Init();
        bt res=Xor(cal(B),cal(A-1));
        ll val=1,ans=0;
        for(int i=0;i<72;++i)
        {
            if(res.test(i)) ans=(ans+val)%mod;
            val=val*2%mod;
        }
        return (ans%mod+mod)%mod;
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值