TopCoder SRM622 DIV1

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值