好久没写博客了,最近状况不太好,有些力不从心,不知道还能走多远,留给自己的时间不多了……正好今天打了场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;
}
};