2016"百度之星" - 初赛(Astar Round2A)

题目链接:

  http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=701

1001 :

 矩阵快速幂

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include<queue>
#include<vector>
using namespace std;
const int N = 5e5+20, M = 1e2+10, mod = 1000000007,inf = 1e9;
typedef long long ll;
struct Matix {
    ll arr[M][M];
};
ll x,m,k,c;
Matix mul(Matix a,Matix b,ll hang ,ll lie) {
    Matix ans;
    memset(ans.arr,0,sizeof(ans.arr));
    for(int i=1;i<=hang;i++) {
      for(int t=1;t<=lie;t++)
        for(int j=1;j<=lie;j++) {
         ans.arr[i][t]+=(a.arr[i][j]*b.arr[j][t]);
         ans.arr[i][t]%=k;
        }
    }
    return ans;
}
Matix pow(Matix ans,Matix a,ll x) {
    while(x) {
        if(x&1) ans=mul(ans,a,2,2);
        a=mul(a,a,2,2);
        x/=2;
    }
    return ans;
}
int main(){
    ll x,y,z;
    int T,cas=1;
    scanf("%d",&T);
    while(T--) {
        scanf("%I64d%I64d%I64d%I64d",&x,&m,&k,&c);
        Matix fir,sec;
        Matix now;
        now.arr[1][1]=x;
        now.arr[1][2]=x;
        memset(fir.arr,0,sizeof(fir.arr));
        sec.arr[1][1]=10;sec.arr[1][2]=0;
        sec.arr[2][1]=1;sec.arr[2][2]=1;
        fir.arr[1][1]=1;
        fir.arr[2][2]=1;
        fir=pow(fir,sec,m-1);fir=mul(now,fir,2,2);
        printf("Case #%d:\n",cas++);
        if(fir.arr[1][1]==c)puts("Yes");
        else puts("No");
    }
    return 0;
}
View Code

1002:

 状态压缩DP

  我们设定dp[1<<16][16]:dp[i][j]:i为当前选取的状态并以第j个数结尾的最大值,那么答案就是 max{dp[全集][k]} k属于0到n-1

  对于dp[i][j] , i这个状态已经填了x个数,我们准备填第x+1个数时, 如果当前x+1位置必填某个数,那么 就只更新以规定的这个数结尾转移方程

  如果没有那就 枚举那么可以任意放的数来更新相应的状态及答案

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include<queue>
#include<vector>
using namespace std;
const int N = 1<<17, M = 1e6+10, mod = 1000000007,inf = 1e9;
typedef long long ll;

ll dp[1<<17][17];
int n,a[N],p[N],H[N],F[N];
int main() {
    int T,cas = 1;
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        memset(H,0,sizeof(H));
        memset(F,-1,sizeof(F));
        int tmp = 0;
        for(int i=0;i<n;i++) {
            scanf("%d%d",&a[i],&p[i]);
            if(p[i]!=-1)
             H[i] = 1,F[p[i]] = i;
        }
        for(int i=0;i<(1<<n);i++)
            for(int j=0;j<n;j++) dp[i][j] = -1e18;
  //      for(int i=0;i<n;i++)
    //        for(int j=0;j<n;j++) if(i!=j&&!H[i]&&!H[j]) dp[(1<<i)|(1<<j)][j] = a[i]*a[j], dp[(1<<i)|(1<<j)][i] = a[i]*a[j];
       if(F[0]!=-1) dp[(1<<F[0])][F[0]] = 0;
       else {
        for(int i=0;i<n;i++) {
            if(!H[i]) dp[(1<<i)][i] = 0;
        }
       }
       int U = (1<<n) - 1;
        for(int i=1;i<=U;i++) {
            int counts = 0;
            for(int j=0;j<n;j++) if((1<<j)&(i)) counts++;
            if(F[counts]!=-1) {
                counts = F[counts];
                for(int j=0;j<n;j++) if(i&(1<<j)&&counts!=j)dp[i|(1<<(counts))][counts] = max(dp[i][j]+a[j]*a[counts],dp[i|(1<<counts)][counts]);
            }
            else {
                for(int k=0;k<n;k++) {
                    if((1<<k)&(i))
                    for(int j=0;j<n;j++) {
                       if(!((1<<j)&i)) {
                            dp[i|(1<<j)][j] = max(dp[i|(1<<j)][j],dp[i][k]+a[k]*a[j]);
                        }
                    }
                }
            }
        }
        printf("Case #%d:\n",cas++);
        ll ans = -1e18;
        for(int i=0;i<n;i++) ans = max(dp[U][i],ans) ;
        printf("%I64d\n",ans);
    }
    return 0;
}
View Code

 1004:D Game

  区间dp

  设定dp[i][j]为i到j这个区间的最大答案,每次去选择连续不连续的2个/3个去删除,暴力转移就好

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include<map>
using namespace std;
const int N = 315, M = 30005, mod = 1e9 + 7, inf = 0x3f3f3f3f;
typedef long long ll;

int dp[N][N];
ll a[N],d;
map<ll,int > mp;
int dfs(int l,int r) {
    if(dp[l][r]!=-1) return dp[l][r];
    int& ret = dp[l][r];
    ret = 0;
    if(l>=r) return ret;

    if(l+1==r) {
        if(mp[a[r]-a[l]]) return (ret = 2);
        else return (ret = 0);
    }

    int tmp = 0;
    if(mp[a[r]-a[l]]) tmp+=2;// cout<<a[r]-a[l]<<endl;
    if(dfs(l+1,r-1)==((r-1)-(l+1)+1)) ret = tmp+((r-1)-(l+1)+1);
    if(abs(a[r]-a[l])%2==0&&mp[(a[r]-a[l])/2])
    for(int i=l+1;i<r;i++) {
        tmp = 0;
        if(a[r]-a[i]==a[i]-a[l]&&mp[a[i]-a[l]]) {
            tmp = 3;
        }
        else continue;
        if(tmp+dfs(l+1,i-1)+dfs(i+1,r-1)==r-l+1) {
            ret = r-l+1;break;
        }
    }

    for(int i=l+1;i<r;i++) {
        ret = max(ret,dfs(l,i)+dfs(i+1,r));
    }
    return ret;
}
int main() {
    int T,m,n;
    scanf("%d",&T);
    while(T--) {
        mp.clear();
        memset(dp,-1,sizeof(dp));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);
        for(int i=1;i<=m;i++) scanf("%I64d",&d),mp[d] = 1;
        printf("%d\n",dfs(1,n));
    }
    return 0;
}

/*
1
7 2
1 5 8 101 59 62 201
100 3
*/
View Code

1005:

 预处理+dfs

 预处理每种长度,每种长度的答案

 再对对应长度dfs求出答案

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include<queue>
#include<vector>
using namespace std;
const int N = 1e3+20, M = 1e6+10, mod = 1000000007,inf = 1e9;
typedef long long ll;

ll len[N],dp[N],L,R;
ll dfs(ll x){
    if(x<=0) return 0;
    if(x<=2) return x;
    if(x==3) return 2;
    ll ans=0;
    int pos = upper_bound(len+1,len+62,x) - len - 1;
    if(len[pos]==x) return dp[pos];
    if(x-len[pos]==1) return dp[pos]+1;
    ll ret = dp[pos]+1;
    ll shen = x-len[pos]-1;
    return ret+shen - dp[pos] + dfs(len[pos] - shen);
}
int main() {
    dp[1] = 1;
    len[1] = 1;
    for(int i=2;i<=61;i++) {
        len[i] = len[i-1]*2+1;
    }
    for(int i=2;i<=61;i++) {
        dp[i] = dp[i-1] + 1 + len[i-1] - dp[i-1];
    }
    int T;
    scanf("%d",&T);
    while(T--) {
        scanf("%I64d%I64d",&L,&R);
        printf("%I64d\n",dfs(R)-dfs(L-1));
    }
    return 0;
}
View Code

1006

 优先队列

 首先按照拓扑,将入度为0的压入,优先位置大的放前面。。。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include<queue>
#include<vector>
using namespace std;
const int N = 5e5+20, M = 1e6+10, mod = 1000000007,inf = 1e9;
typedef long long ll;


int k,c,x,d[N],n,m,vis[N];
vector<int >G[N]; int ans[N];
int main() {
    int T;
    int cas = 1;
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) G[i].clear();
        for(int i=1;i<=n;i++) vis[i] = 0,d[i] =  0;
        for(int i=1;i<=m;i++) {
            int a,b;
            scanf("%d%d",&a,&b);
            G[a].push_back(b);
            d[b]++;
        }
        priority_queue<int > q;
        
        for(int i=1;i<=n;i++) {
            if(d[i]==0) q.push(i);
        }
        int cnt =0 ;
        while(!q.empty()) {
            int k  = q.top();
            ans[++cnt] = k;
          //  cout<<k<<endl;
            q.pop();
            for(int i=0;i<G[k].size();i++) {
                d[G[k][i]]--;
                if(d[G[k][i]]==0&&!vis[G[k][i]]) {
                    q.push(G[k][i]);

                    vis[G[k][i]] = 1;
                }
            }
        }
        int mi = 1e9;
        ll aa = 0;
        for(int i=1;i<=cnt;i++) {
            mi = min(ans[i],mi);
            aa  = aa + mi;
        }
        printf("%I64d\n",aa);
    }
    return 0;
}
View Code

 

posted @ 2016-05-21 17:51  meekyan  阅读(782)  评论(2编辑  收藏  举报