250
floyd 挺新鲜的一种用法,之前没有注意过,这次学习了
// BEGIN CUT HERE
// END CUT HERE
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <map>
#include <utility>
#include <cmath>
#include <queue>
#include <stack>
#include <cstring>
#include <cstdlib>
#include <set>
#include <iterator>
#include <sstream>
#include <ctime>
using namespace std;
typedef long long LL;
#define sz(x) x.size()
#define pb push_back
#define mp make_pair
#define clr(x,a) memset(x,a,sizeof(x))
#define cpy(x,a) memcpy(x,a,sizeof(x))
class BuildingRoutes {
public:
int d[60][60];
int ct[60][60];
int a[60][60];
int build(vector <string> dist, int T) {
int n=sz(dist[0]);
int ret=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
a[i][j]=dist[i][j]-'0';
d[i][j]=a[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]);
memset(ct,0,sizeof(ct));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
if(i==j) continue;
for(int p=0;p<n;p++)
for(int q=0;q<n;q++)
{
if(p==q) continue;
if(d[i][p]+a[p][q]+d[q][j]==d[i][j]){
ct[p][q]++;
if(ct[p][q]==T)
ret+=a[p][q];
}
}
}
return ret;
}
// BEGIN CUT HERE
// END CUT HERE
};
// BEGIN CUT HERE
// END CUT HERE
500
树形DP
尝试了两种写法,一种记忆化搜索,一种递推,记忆化搜索效率明显较高
// BEGIN CUT HERE
// END CUT HERE
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <map>
#include <utility>
#include <cmath>
#include <queue>
#include <stack>
#include <cstring>
#include <cstdlib>
#include <set>
#include <iterator>
#include <sstream>
#include <ctime>
using namespace std;
typedef long long LL;
#define sz(x) x.size()
#define pb push_back
#define mp make_pair
#define clr(x,a) memset(x,a,sizeof(x))
#define cpy(x,a) memcpy(x,a,sizeof(x))
//dp[x][l] : 最大长度不超过l以x为root的子树最少的集合数
class Ethernet {
public:
int dp[60][700];
vector<pair<int,int> > t[60];
int limit;
/*void dfs(int u){
int n=sz(t[u]);
for(int i=0;i<n;i++)
dfs(t[u][i].first);
for(int i=0;i<=limit;i++){ //枚举极限
//注意对于每棵子树的每一个极限深度,我们都要计算一次一个都不连的情况下的集合数量,
//因为,让它的子树的深度为limit可以减少最后的答案·总和。 总结一句话,这个地方很容易少
//少了就是考虑不周到。下次一定要注意。不一定是都不满足约束时才一颗都不连,有时候我们可以自己选择不连。
dp[u][i]=1;
for(int j=0;j<n;j++)
dp[u][i]+=dp[t[u][j].first][limit];
for(int j=0;j<n;j++){ //枚举最大深度位于那棵子树中
int d=t[u][j].second;
int x=t[u][j].first;
for(int m=d;m<=i;m++){ //枚举最大深度
int sum=dp[x][m-d];
for(int k=0;k<n;k++){ //枚举其他子树
if(k==j) continue;
int z=t[u][k].first;
int tmp=dp[z][limit]; //其他子树不连
int mins=min(limit-m,m)-t[u][k].second;
if(mins>=0) //如果能连上则比较大小
tmp=min(dp[z][mins]-1,tmp);
sum+=tmp;
}
dp[u][i]=min(sum,dp[u][i]);
}
}
}
}*/
int dfs(int u,int maxDep){
if(dp[u][maxDep]!=-1)
return dp[u][maxDep];
int n=sz(t[u]);
int ret=1;
for(int i=0;i<n;i++)
ret+=dfs(t[u][i].first,limit);
for(int i=0;i<n;i++){
int x=t[u][i].first;
int d=t[u][i].second;
for(int m=d;m<=maxDep;m++){
int sum=dfs(x,m-d);
for(int j=0;j<n;j++){
if(i==j) continue;
int y=t[u][j].first;
int tmp=dfs(y,limit); // 不连接
int mins=min(limit-m,m)-t[u][j].second;
if(mins>=0)
tmp=min(tmp,dfs(y,mins)-1);
sum+=tmp;
}
ret=min(ret,sum);
}
}
return dp[u][maxDep]=ret;
}
int connect(vector <int> parent, vector <int> dist, int maxDist) {
int n=sz(parent)+1;
limit=maxDist;
for(int i=0;i<n;i++) t[i].clear();
for(int i=0;i<n-1;i++)
t[parent[i]].pb(mp(i+1,dist[i]));
//dfs(0);
//return dp[0][limit];
clr(dp,-1);
return dfs(0,limit);
}
// BEGIN CUT HERE
// END CUT HERE
};
// BEGIN CUT HERE
// END CUT HERE
900
一道关于斐波拉契数的dp
对于区间[a,b]处理成前缀异或值 [0,a-1] [0,b]再分别异或。
// BEGIN CUT HERE
// END CUT HERE
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <map>
#include <utility>
#include <cmath>
#include <queue>
#include <stack>
#include <cstring>
#include <cstdlib>
#include <set>
#include <iterator>
#include <sstream>
#include <ctime>
using namespace std;
typedef long long LL;
#define sz(x) x.size()
#define pb push_back
#define mp make_pair
#define clr(x,a) memset(x,a,sizeof(x))
#define cpy(x,a) memcpy(x,a,sizeof(x))
const long long mod=1000000007;
class FibonacciXor {
public:
vector<long long> fib;
int fibn;
vector<int> getFibonaccinal(long long x){
vector<int> res(fibn,0);
for(int i=fibn-1;i>=0;i--){
if(x>=fib[i]){
res[i]=1;
x-=fib[i];
}
}
return res;
}
vector<int> getPrefix(long long x){
vector<int> fbase=getFibonaccinal(x);
vector<int> res(fibn);
int dp[76][2][2];
for(int i=0;i<fibn;i++){
for(int less=0;less<2;less++)
for(int last=0;last<2;last++)
dp[0][less][last]=1;
for(int j=1;j<=fibn;j++){
for(int less=0;less<2;less++){
for(int last=0;last<2;last++){
int mx=1;
dp[j][less][last]=0;
if((less==0&&fbase[j-1]==0) || last==1) mx=0;
for(int v=0;v<=mx;v++){
if(v==0&&j-1==i) continue;
int newless=(less||(fbase[j-1]>v));
dp[j][less][last]^=dp[j-1][newless][v];
}
}
}
}
res[i]=dp[fibn][0][0];
}
return res;
}
void makeFib(long long x){
long long a=1,b=2,t;
fib.clear();
while(a<=x){
fib.pb(a);
t=a;
a=b;
b=t+a;
}
fibn=sz(fib);
}
int find(long long A, long long B) {
makeFib(B);
vector<int> Abit=getPrefix(A-1);
vector<int> Bbit=getPrefix(B);
long long ret=0;
for(int i=fibn-1;i>=0;i--){
ret*=2;
ret%=mod;
if(Abit[i]!=Bbit[i])
ret++;
ret%=mod;
}
return (int)ret;
}
// BEGIN CUT HERE
// END CUT HERE
};
// BEGIN CUT HERE
// END CUT HERE