山东省第四届ACM程序设计竞赛部分题解

A : Rescue The Princess

题意:

给你平面上的两个点A,B,求点C使得A,B,C逆时针成等边三角形。

思路:

http://www.cnblogs.com/E-star/archive/2013/06/11/3131563.html   向量的旋转。

直接套公式就行,或者我们可以找到等式解一个二元一次方程然后向量判断方向即可。我比较懒,就写了向量旋转的。

#include <iostream>  

#include <cstdio>  

#include <cmath>  

#include <vector>  

#include <cstring>  

#include <algorithm>  

#include <string>  

#include <set>  

#include <functional>  

#include <numeric>  

#include <sstream>  

#include <stack>  

#include <map>  

#include <queue>  

  

#define CL(arr, val)    memset(arr, val, sizeof(arr))  

  

#define lc l,m,rt<<1  

#define rc m + 1,r,rt<<1|1  

#define pi acos(-1.0)  

#define ll __int64  

#define L(x)    (x) << 1  

#define R(x)    (x) << 1 | 1  

#define MID(l, r)   (l + r) >> 1  

#define Min(x, y)   (x) < (y) ? (x) : (y)  

#define Max(x, y)   (x) < (y) ? (y) : (x)  

#define E(x)        (1 << (x))  

#define iabs(x)     (x) < 0 ? -(x) : (x)  

#define OUT(x)  printf("%I64d\n", x)  

#define lowbit(x)   (x)&(-x)  

#define Read()  freopen("din.txt", "r", stdin)  

#define Write() freopen("dout.txt", "w", stdout);  

  

  

#define M 137  

#define N 22  

  

using namespace std;  

  

  

const int inf = 0x7f7f7f7f;  

const int mod = 1000000007;  

  

double xx1,yy1,xx2,yy2;  

  

int main()  

{  

//    Read();  

    int T;  

    scanf("%d",&T);  

    while (T--)  

    {  

        scanf("%lf%lf%lf%lf",&xx1,&yy1,&xx2,&yy2);  

//        printf("%.3lf %.3lf %.3lf %.3lf\n",xx1,yy1,xx2,yy2);  

        double tx = xx2 - xx1;  

        double ty = yy2 - yy1;  

  

        double x = tx*(1.0/2.0) - ty*(sqrt(3.0)/2.0) + xx1;  

        double y = ty*(1.0/2.0) + tx*(sqrt(3.0)/2.0) + yy1;  

        printf("(%.2lf,%.2lf)\n",x,y);  

    }  

    return 0;  

}  
View Code

 

B: Thrall’s Dream

题意:

给定n个点,m条有向边,求解任意两点是否可达。 

思路:

比赛时直接枚举每一个点,然后bfs判断就行,时间复杂度为O(n +m) , 这题tarjan缩点然后判断是否为链就行O(n + m)

#include <iostream>  

#include <cstdio>  

#include <cmath>  

#include <vector>  

#include <cstring>  

#include <algorithm>  

#include <string>  

#include <set>  

#include <functional>  

#include <numeric>  

#include <sstream>  

#include <stack>  

#include <map>  

#include <queue>  

  

#define CL(arr, val)    memset(arr, val, sizeof(arr))  

  

#define lc l,m,rt<<1  

#define rc m + 1,r,rt<<1|1  

#define pi acos(-1.0)  

#define ll __int64  

#define L(x)    (x) << 1  

#define R(x)    (x) << 1 | 1  

#define MID(l, r)   (l + r) >> 1  

#define Min(x, y)   (x) < (y) ? (x) : (y)  

#define Max(x, y)   (x) < (y) ? (y) : (x)  

#define E(x)        (1 << (x))  

#define iabs(x)     (x) < 0 ? -(x) : (x)  

#define OUT(x)  printf("%I64d\n", x)  

#define lowbit(x)   (x)&(-x)  

#define Read()  freopen("din.txt", "r", stdin)  

#define Write() freopen("dout.txt", "w", stdout);  

  

  

#define M 10007  

#define N 2007  

  

using namespace std;  

  

  

const int inf = 0x7f7f7f7f;  

const int mod = 1000000007;  

  

struct node  

{  

    int v;  

    int next;  

}g[M];  

int head[N],ct;  

bool ok[N][N];  

bool vt[N];  

int n,m;  

  

void add(int u,int v)  

{  

    g[ct].v = v;  

    g[ct].next = head[u];  

    head[u] = ct++;  

}  

void bfs(int s)  

{  

    int i;  

    for (i = 1; i <= n; ++i) vt[i] = false;  

    vt[s] = true;  

    queue<int> Q;  

    Q.push(s);  

    while (!Q.empty())  

    {  

        int u = Q.front(); Q.pop();  

        for (i = head[u]; i != -1; i = g[i].next)  

        {  

            int v = g[i].v;  

            if (!vt[v])  

            {  

                vt[v] = true;  

                ok[s][v] = true;  

                Q.push(v);  

            }  

        }  

    }  

}  

int main()  

{  

//    Read();  

    int T;  

    int i,j;  

    scanf("%d",&T);  

    int cas = 1;  

    while (T--)  

    {  

       scanf("%d%d",&n,&m);  

       CL(head,-1); ct = 0;  

       int x,y;  

       for (i = 0; i < m; ++i)  

       {  

           scanf("%d%d",&x,&y);  

           add(x,y);  

       }  

       CL(ok,false);  

       for (i = 1; i <= n; ++i) ok[i][i] = true;  

       for (i = 1; i <= n; ++i) bfs(i);  

  

       bool flag = false;  

       for (i = 1; i <= n && !flag; ++i)  

       {  

           for (j = 1; j <= n && !flag; ++j)  

           {  

               if (ok[i][j] || ok[j][i]) continue;  

               else  

               {  

                   flag = true;  

                   break;  

               }  

           }  

       }  

       if (!flag) printf("Case %d: Kalimdor is just ahead\n",cas++);  

       else printf("Case %d: The Burning Shadow consume us all\n",cas++);  

    }  

    return 0;  

}  
View Code

 

C: A^X mod P

题意:

题意很简单,看题就知道。 

思路:

在求A^X 幂时,快速幂求的话,是O(10^6*log(n)*40) = O(10^9) 肯定会超时,

我们将X转化成 x = i*k + j。这样先在数组可以表示的范围内找到一个k,然后保存A^(1---k)的值,然后再将求出(A^k)^i 保存在数组里,这样每次求A^x,便可以通过这两个数组在O(1)的时间复杂度内求出来,这样时间复杂度就变成了O(10^6*40) = O(4*10^7)了

#include <iostream>  

#include <cstdio>  

#include <cmath>  

#include <vector>  

#include <cstring>  

#include <algorithm>  

#include <string>  

#include <set>  

#include <functional>  

#include <numeric>  

#include <sstream>  

#include <stack>  

#include <map>  

#include <queue>  

  

#define CL(arr, val)    memset(arr, val, sizeof(arr))  

  

#define lc l,m,rt<<1  

#define rc m + 1,r,rt<<1|1  

#define pi acos(-1.0)  

#define ll long long  

#define L(x)    (x) << 1  

#define R(x)    (x) << 1 | 1  

#define MID(l, r)   (l + r) >> 1  

#define Min(x, y)   (x) < (y) ? (x) : (y)  

#define Max(x, y)   (x) < (y) ? (y) : (x)  

#define E(x)        (1 << (x))  

#define iabs(x)     (x) < 0 ? -(x) : (x)  

#define OUT(x)  printf("%I64d\n", x)  

#define lowbit(x)   (x)&(-x)  

#define Read()  freopen("din.txt", "r", stdin)  

#define Write() freopen("dout.txt", "w", stdout);  

  

  

#define M 33333  

#define N 31622  

using namespace std;  

const int mod = 1000000007;  

  

ll powB[M + 10];  

ll powA[N + 10];  

  

ll n, A, K, a, b, m, P;  

  

void init()  

{  

    powA[0] = 1;  

    for (int i = 1; i <= N; ++i)  

    {  

        powA[i] = powA[i - 1]*A%P;  

    }  

    ll tmp = powA[N];  

    powB[0] = 1;  

    for (int i = 1; i <= M; ++i)  

    {  

        powB[i] = powB[i - 1]*tmp%P;  

    }  

}  

void solve(int cas)  

{  

    ll fx = K;  

    ll ans = 0;  

    for (int i = 1; i <= n; ++i)  

    {  

        ans = (ans + powB[fx/N]*powA[fx%N]%P)%P;  

        fx = (a*fx + b)%m;  

    }  

    printf("Case #%d: %lld\n",cas++,ans);  

}  

int main()  

{  

    int T;  

    int cas = 1;  

    scanf("%d",&T);  

  

    while (T--)  

    {  

        cin>>n>>A>>K>>a>>b>>m>>P;  

        init();  

        solve(cas++);  

    }  

    return 0;  

}  

   
View Code

 

D: Rubik’s cube

好像是个模拟题,还没写

E: Mountain Subsequences

题意:

给你一个长度为m的字符串仅由小写英文字母组成,求满足a1 < ...< ai < ai+1 < Amax > aj > aj+1 > ... > an的子串的个数

思路:
首先它仅包含26个英文字母,我们只要枚举每一个位置,然后记录每个位置左边满足条件的个数,右边满足条件的个数,最后乘起来就是了,那么我们怎么记录左边,右边满足的个数的呢?

dp[c]表示以字符c结尾的满足情况的个数,dl[i]表示第i个位置左边满足条件的个数,dr[i]表示第i个位置右边满足条件的个数,

dp[c] = (dl[i] + 1);  s[i] = c; 1表示的s[i]单独一个时满足的情况,dl[i]表示他左边的满足的各种情况+s[i] 后满足情况的。

#include <iostream>  

#include <cstdio>  

#include <cmath>  

#include <vector>  

#include <cstring>  

#include <algorithm>  

#include <string>  

#include <set>  

#include <functional>  

#include <numeric>  

#include <sstream>  

#include <stack>  

#include <map>  

#include <queue>  

  

#define CL(arr, val) memset(arr, val, sizeof(arr))  

  

#define lc l,m,rt<<1  

#define rc m + 1,r,rt<<1|1  

#define pi acos(-1.0)  

#define ll long long  

#define L(x)    (x) << 1  

#define R(x)    (x) << 1 | 1  

#define MID(l, r)   (l + r) >> 1  

#define Min(x, y)   (x) < (y) ? (x) : (y)  

#define Max(x, y)   (x) < (y) ? (y) : (x)  

#define E(x)        (1 << (x))  

#define iabs(x)     (x) < 0 ? -(x) : (x)  

#define OUT(x)  printf("%I64d\n", x)  

#define lowbit(x)   (x)&(-x)  

#define Read()  freopen("data.in", "r", stdin)  

#define Write() freopen("d.out", "w", stdout)  

  

  

#define M 100007  

#define N 100007  

  

using namespace std;  

  

  

const int inf = 0x7f7f7f7f;  

const int mod = 1000000007;  

int dp[27],dl[N],dr[N];  

int n;  

char ts[N];  

int s[N];  

  

int main()  

{  

//    Read();  

    int i,j;  

    while (~scanf("%d",&n))  

    {  

        scanf("%s",ts);  

        for (i = 0; i < n; ++i) s[i] = ts[i] - 'a';  

  

        CL(dp,0); CL(dl,0); CL(dr,0);  

  

        for (i = 0; i < n; ++i)  

        {  

            for (j = 0; j < s[i]; ++j) dl[i] += dp[j];  

  

            dl[i] %= 2012;  

            dp[s[i]] += (dl[i] + 1);  

            dp[s[i]] %= 2012;  

        }  

  

        CL(dp,0);  

        for (i = n - 1; i >= 0; --i)  

        {  

            for (j = 0; j < s[i]; ++j) dr[i] += dp[j];  

  

            dr[i] %= 2012;  

            dp[s[i]] += (dr[i] + 1);  

            dp[s[i]] %= 2012;  

        }  

        int ans = 0;  

        for (i = 0; i < n; ++i)  

        {  

            ans += dl[i]*dr[i];  

            ans %= 2012;  

        }  

        printf("%d\n",ans);  

    }  

    return 0;  

}  
View Code

 

F: Alice and Bob

题意:

给出一个多项式:(a0*x^(2^0)+1) * (a1 * x^(2^1)+1)*.......*(an-1 * x^(2^(n-1))+1)

输入P,求X^p 前边的系数。

思路:

首先P肯定是一个二进制表示的数,并且唯一。我们只要将p转化成二进制数,然后乘上系数就好了。

#include <iostream>  

#include <cstdio>  

#include <cmath>  

#include <vector>  

#include <cstring>  

#include <algorithm>  

#include <string>  

#include <set>  

#include <functional>  

#include <numeric>  

#include <sstream>  

#include <stack>  

#include <map>  

#include <queue>  

   

#define CL(arr, val)    memset(arr, val, sizeof(arr))  

   

#define lc l,m,rt<<1  

#define rc m + 1,r,rt<<1|1  

#define pi acos(-1.0)  

#define ll long long  

#define L(x)    (x) << 1  

#define R(x)    (x) << 1 | 1  

#define MID(l, r)   (l + r) >> 1  

#define Min(x, y)   (x) < (y) ? (x) : (y)  

#define Max(x, y)   (x) < (y) ? (y) : (x)  

#define E(x)        (1 << (x))  

#define iabs(x)     (x) < 0 ? -(x) : (x)  

#define OUT(x)  printf("%I64d\n", x)  

#define lowbit(x)   (x)&(-x)  

#define Read()  freopen("din.txt", "r", stdin)  

#define Write() freopen("dout.txt", "w", stdout);  

   

   

#define M 137  

#define N 55  

   

using namespace std;  

   

   

const int inf = 0x7f7f7f7f;  

const int mod = 1000000007;  

   

int a[N],b[60];  

   

int main()  

{  

   int T,i;  

   int n,m;  

   scanf("%d",&T);  

   while (T--)  

   {  

       scanf("%d",&n);  

       CL(a,0);  

       for (i = 0; i < n; ++i) scanf("%d",&a[i]);  

   

       scanf("%d",&m);  

       int top;  

       ll p;  

       while (m--)  

       {  

           cin>>p; top = 0;  

           if (p == 0)  

           {  

               printf("1\n");  

               continue;  

           }  

           while (p)  

           {  

               b[top++] = p%2;  

               p /= 2;  

           }  

           int ans = 1;  

           for (i = 0; i < top; ++i)  

           {  

               if (b[i])  ans = ans*a[i]%2012;  

           }  

   

          printf("%d\n",ans);  

       }  

   }  

   return 0;  

}   

  
View Code

 

G: A-Number and B-Number

题意:
给出Anum的定义,包含7或者能被7整除的数,

然后给出Bnum的定义,a[i] = Anum 表示i不是Anum

输入n输出第n个Bnum

思路:

二分 + 数位DP

首先我们二分一个数mid,找到<=mid的mid最小的区间满足等于n个Bnum的数,那么这个数肯定是Bnum。

关键是如何求区间内Bnum的数量,我们转化为先求一下Anum的数量,然后对Anum数量这个区间再求Anum数量就得到了这个区间Bnum的数量了。在求Anum数量时就用到了数位DP

 

#include <iostream>

#include <cstdio>

#include <cmath>

#include <vector>

#include <cstring>

#include <algorithm>

#include <string>

#include <set>

#include <functional>

#include <numeric>

#include <sstream>

#include <stack>

#include <map>

#include <queue>

 

#define CL(arr, val) memset(arr, val, sizeof(arr))

 

#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define L(x)    (x) << 1

#define R(x)    (x) << 1 | 1

#define MID(l, r)   (l + r) >> 1

#define Min(x, y)   (x) < (y) ? (x) : (y)

#define Max(x, y)   (x) < (y) ? (y) : (x)

#define E(x)        (1 << (x))

#define iabs(x)     (x) < 0 ? -(x) : (x)

#define OUT(x)  printf("%I64d\n", x)

#define lowbit(x)   (x)&(-x)

#define Read()  freopen("data.in", "r", stdin)

#define Write() freopen("d.out", "w", stdout)

#define ll unsigned long long

 

 

#define M 100007

#define N 100007

 

using namespace std;

 

const int inf = 0x7f7f7f7f;

const int mod = 1000000007;

 

const ll R = ((1uLL<<63) - 1);

 

ll dp[25][7][2];

int bit[25];

ll n;

 

ll dfs(int len,int pre,int flag,int limit)

{

    if (len == -1) return flag||pre == 0;

    if (!limit && dp[len][pre][flag] != -1uLL) return dp[len][pre][flag];

 

    int up = limit?bit[len]:9;

    ll ans = 0;

    for (int i = 0; i <= up; ++i)

    {

        int tpre = (pre*10 + i)%7;

        int tflag = (flag || i == 7);

        int tlimit = (limit && i == up);

        ans += dfs(len - 1,tpre,tflag,tlimit);

    }

    if (!limit) dp[len][pre][flag] = ans;

    return ans;

}

ll getR(ll m)

{

    int len  = 0;

    while (m)

    {

        bit[len++] = m%10;

        m /= 10;

    }

    return dfs(len - 1,0,0,1) - 1;

}

ll solve(ll m)

{

    ll cnt1 = getR(m);

    ll cnt2 = cnt1 - getR(cnt1);

    return cnt2;

}

int main()

{

//    Read();

    while (~scanf("%lld",&n))

    {

        CL(dp,-1);

        ll l = 0,r = R;

        ll ans = 0;

        while (l <= r)

        {

            ll mid = (l + r)>>1;

            if (solve(mid) < n) l = mid + 1;

            else

            {

                ans = mid;

                r = mid - 1;

            }

        }

        printf("%lld\n",ans);

    }

    return 0;

}

 
View Code

 

H: Boring Counting

题意:

给你n个数,m个询问(N and M (1 <= N, M <= 50000)),询问包含四个数L,R,A,B 求区间[L,R]里面在区间[A,B]的数的个数。

思路:

首先想到的是二维树状数组,或者二维线段树处理,因为数据量太大。但是二维这个维数也不能表示,因为离散化之后50000*50000是不能表示的,那怎么办呢?

划分树,我们只要二分枚举该区间的最小的第几大大于等于A,以及最小的大于B的第几大,然后他们的差值就区间满足条件的个数。时间复杂度为O(nlog(n)*log(n));

这里求区间第几大用到了划分树。

#include <iostream>  

#include <cstdio>  

#include <cmath>  

#include <vector>  

#include <cstring>  

#include <algorithm>  

#include <string>  

#include <set>  

#include <functional>  

#include <numeric>  

#include <sstream>  

#include <stack>  

#include <map>  

#include <queue>  

  

#define CL(arr, val)    memset(arr, val, sizeof(arr))  

  

#define lc l,m,rt<<1  

#define rc m + 1,r,rt<<1|1  

#define pi acos(-1.0)  

#define ll __int64  

#define L(x)    (x) << 1  

#define R(x)    (x) << 1 | 1  

#define MID(l, r)   (l + r) >> 1  

#define Min(x, y)   (x) < (y) ? (x) : (y)  

#define Max(x, y)   (x) < (y) ? (y) : (x)  

#define E(x)        (1 << (x))  

#define iabs(x)     (x) < 0 ? -(x) : (x)  

#define OUT(x)  printf("%I64d\n", x)  

#define Read()  freopen("din.txt", "r", stdin)  

#define Write() freopen("dout.in", "w", stdout);  

  

  

#define M 50007  

#define N 50007  

  

using namespace std;  

  

  

const int inf = 0x7f7f7f7f;  

  

struct node{  

    int l,r;  

    int mid(){  

        return (l + r)>>1;  

    }  

}tt[N<<2];  

int toLeft[30][N];  

int val[30][N],sorted[N];  

int n,q,m;  

  

void build(int l,int r,int rt,int d){  

    int i;  

    tt[rt].l = l;  

    tt[rt].r = r;  

    if (l == r) return ;  

    int m = tt[rt].mid();  

    int lsame = m - l + 1;  

  

    for (i = l; i <= r; ++i){  

        if (val[d][i] < sorted[m]) lsame--;  

    }  

  

    int lpos = l;  

    int rpos = m + 1;  

    int same = 0;  

  

    for (i = l; i <= r; ++i){  

        if (i == l) toLeft[d][i] = 0;  

        else toLeft[d][i] = toLeft[d][i - 1];  

  

        if (val[d][i] < sorted[m]){  

            toLeft[d][i]++;  

            val[d + 1][lpos++] = val[d][i];  

        }  

        else if (val[d][i] > sorted[m]){  

            val[d + 1][rpos++] = val[d][i];  

        }  

        else{  

            if (same < lsame){  

                toLeft[d][i]++;  

                val[d + 1][lpos++] = val[d][i];  

                same++;  

            }  

            else{  

                val[d + 1][rpos++] = val[d][i];  

            }  

        }  

    }  

    build(lc,d + 1);  

    build(rc,d + 1);  

}  

  

int query(int L,int R,int k,int d,int rt){  

    if (L == R){  

        return val[d][L];  

    }  

    int s = 0;  

    int ss = 0;  

    if (L == tt[rt].l){  

        ss = 0;  

        s = toLeft[d][R];  

    }  

    else{  

        ss = toLeft[d][L - 1];  

        s = toLeft[d][R] - toLeft[d][L - 1];  

    }  

    if (k <= s){  

        int newl = tt[rt].l + ss;  

        int newr = newl + s - 1;  

        return query(newl,newr,k,d + 1,rt<<1);  

    }  

    else{  

        int m = tt[rt].mid();  

        int bb = L - tt[rt].l - ss;  

        int b = R - L + 1 - s;  

        int newl = m + bb + 1;  

        int newr = newl + b - 1;  

        return query(newl,newr,k - s,d + 1,rt<<1|1);  

    }  

}  

int BS1(int L,int R,int l,int r,int A)  

{  

    int ans = -1;  

    while (l <= r)  

    {  

        int mid = (l + r)>>1;  

        int res = query(L,R,mid,0,1);  

        if (res >= A)  

        {  

            ans = mid;  

            r = mid - 1;  

        }  

        else l = mid + 1;  

    }  

    return ans;  

}  

int BS2(int L,int R,int l,int r,int B)  

{  

    int ans = 0;  

    while (l <= r)  

    {  

        int mid = (l + r)>>1;  

        int res = query(L,R,mid,0,1);  

        if (res > B)  

        {  

            ans = mid;  

            r = mid - 1;  

        }  

        else l = mid + 1;  

    }  

    if (ans == 0) return r;  

    else return ans - 1;  

}  

int main()  

{  

//    Read();  

  

    int T,i;  

    int cas = 1;  

    scanf("%d",&T);  

    while (T--)  

    {  

        scanf("%d%d",&n,&m);  

        for (i = 1; i <= n; ++i)  

        {  

            scanf("%d",&val[0][i]);  

            sorted[i] = val[0][i];  

        }  

        sort(sorted + 1,sorted + 1 + n);  

        build(1,n,1,0);  

  

        printf("Case #%d:\n",cas++);  

        int x,y,A,B;  

        while (m--)  

        {  

            scanf("%d%d%d%d",&x,&y,&A,&B);  

  

            int l = 1;  

            int r = y - x + 1;  

            int cnt1 = BS1(x,y,l,r,A);  

            int cnt2 = BS2(x,y,l,r,B);  

//            printf(">>>>%d %d %d %d %d %d\n",x,y,A,B,cnt1,cnt2);  

            if (cnt1 == -1)  

            {  

                printf("0\n");  

                continue;  

            }  

            printf("%d\n",cnt2 - cnt1 + 1);  

        }  

    }  

    return 0;  

}  

   
View Code

 

有没有更优的解法,当然有。  我们回到二维树状数组,如果我们求一个矩阵内的和的话,需要知道四个点到源点的的和,然后根据简单的容斥弄出来。这里我们将每个询问离线处理,转化成四个点,然后将点按x轴(表示[l,R])排序,y轴呢则表示[A,B]这样没当插入一点的时候我们就将小于x的所有的给定序列的值查到纵轴所标的区间内,纵轴用一个一维的树状数组即可,然后每当遇到四个点中的所要求的点的时候,计算就行,因为这样保证了纵轴上的点肯定是在[L,R]范围内的,然后我们在根据[A,B]来求一维的值即可。

#include <iostream>  

#include <cstdio>  

#include <cmath>  

#include <vector>  

#include <cstring>  

#include <algorithm>  

#include <string>  

#include <set>  

#include <functional>  

#include <numeric>  

#include <sstream>  

#include <stack>  

#include <map>  

#include <queue>  

  

#define CL(arr, val)    memset(arr, val, sizeof(arr))  

  

#define lc l,m,rt<<1  

#define rc m + 1,r,rt<<1|1  

#define pi acos(-1.0)  

#define ll __int64  

#define L(x)    (x) << 1  

#define R(x)    (x) << 1 | 1  

#define MID(l, r)   (l + r) >> 1  

#define Min(x, y)   (x) < (y) ? (x) : (y)  

#define Max(x, y)   (x) < (y) ? (y) : (x)  

#define E(x)        (1 << (x))  

#define iabs(x)     (x) < 0 ? -(x) : (x)  

#define OUT(x)  printf("%I64d\n", x)  

#define Read()  freopen("din.txt", "r", stdin)  

#define Write() freopen("dout.in", "w", stdout);  

  

  

#define M 50007  

#define N 50007  

  

using namespace std;  

  

  

const int inf = 0x7f7f7f7f;  

  

struct point  

{  

    int x,y;  

    int id;  

    int no;  

}pt[10*N];  

int SM[10*N];  

  

int n,m;  

int c[10*N],a[N],b[10*N];  

int of[N*10][6];  

int ans[N];  

  

int nn;  

  

int lowbit(int x)  

{  

    return (x&(-x));  

}  

void modify(int pos,int val)  

{  

    while (pos <= nn)  

    {  

        c[pos] += val;  

        pos += lowbit(pos);  

    }  

}  

int getsum(int pos)  

{  

    int sum = 0;  

    while (pos > 0)  

    {  

        sum += c[pos];  

        pos -= lowbit(pos);  

    }  

    return sum;  

}  

int BS(int l,int r,int val)  

{  

    while (l <= r)  

    {  

        int mid = (l + r)/2;  

        if (b[mid] == val) return mid;  

        else if (b[mid] < val) l = mid + 1;  

        else r = mid - 1;  

    }  

    return -1;  

}  

int cmp(int x,int y)  

{  

    return x < y;  

}  

int cmpPt(point a,point b)  

{  

    if (a.x != b.x) return a.x < b.x;  

    else return a.y < b.y;  

}  

int main()  

{  

//    Read();  

//    Write();  

    int T,i;  

    int cas = 1;  

    scanf("%d",&T);  

    while (T--)  

    {  

        scanf("%d%d",&n,&m);  

        int k = 0;  

        for (i = 1; i <= n; ++i)  

        {  

            scanf("%d",&a[i]);  

            b[++k] = a[i];  

        }  

  

        int pl = 0;  

        int x1,y1,x2,y2;  

        for (i = 1; i <= m; ++i)  

        {  

            scanf("%d%d%d%d",&x1,&x2,&y1,&y2);  

            b[++k] = y1 - 1; b[++k] = y2;  

  

            pt[pl].x = x1 - 1, pt[pl].y = y1 - 1;  

            pt[pl].id = i,pt[pl++].no = 0;  

  

            pt[pl].x = x1 - 1, pt[pl].y = y2;  

            pt[pl].id = i,pt[pl++].no = 1;  

  

            pt[pl].x = x2, pt[pl].y = y1 - 1;  

            pt[pl].id = i,pt[pl++].no = 2;  

  

            pt[pl].x = x2, pt[pl].y = y2;  

            pt[pl].id = i,pt[pl++].no = 3;  

        }  

  

        sort(b + 1,b + 1 + k,cmp); nn = 1;  

        for (i = 2; i <= k; ++i) if (b[i] != b[i - 1]) b[++nn] = b[i];  

  

        sort(pt,pt + pl,cmpPt);  

        for (i = 0; i < pl; ++i) of[pt[i].id][pt[i].no] = i;  

  

  

        CL(c,0); CL(ans,0);  

        int s = 1;  

        for (i = 0; i < pl; ++i)  

        {  

            int x = pt[i].x;  

            int y = pt[i].y;  

            for (; s <= x; ++s)  

            {  

                int pos = BS(1,nn,a[s]);  

                modify(pos,1);  

            }  

            int p = BS(1,nn,y);  

            SM[i] = getsum(p);  

            if (pt[i].no == 3)  

            {  

                int id = pt[i].id;  

                ans[id] = SM[i] - SM[of[id][1]] - SM[of[id][2]] + SM[of[id][0]];  

            }  

        }  

        printf("Case #%d:\n",cas++);  

        for (i = 1; i <= m; ++i) printf("%d\n",ans[i]);  

    }  

    return 0;  

}  
View Code

 

I:The number of steps

题意:

迷宫是由一个如下的图形组成

     1

    2 3

   4 5 6

 7 8 9 10

...

起始点在1,规定只能望左,左下,右下走,如果不存在左边的点的话,那么往左下,右下的概率为a,b,如果三个点都存在的话,那么往左,左下,右下的概率分别为e,c,d, 如果仅存在左边的点的话,那么走左边点的概率为1

求到达最底层的左下角的点的所用步数的概率。

思路:

很简单的一个概率DP的题目,和置筛子的题目类似。 一定要明白为什么倒着推

学习链接:http://kicd.blog.163.com/blog/static/126961911200910168335852/

#include <iostream>  

#include <cstdio>  

#include <cmath>  

#include <vector>  

#include <cstring>  

#include <algorithm>  

#include <string>  

#include <set>  

#include <functional>  

#include <numeric>  

#include <sstream>  

#include <stack>  

#include <map>  

#include <queue>  

   

#define CL(arr, val) memset(arr, val, sizeof(arr))  

   

#define lc l,m,rt<<1  

#define rc m + 1,r,rt<<1|1  

#define pi acos(-1.0)  

#define ll long long  

#define L(x)    (x) << 1  

#define R(x)    (x) << 1 | 1  

#define MID(l, r)   (l + r) >> 1  

#define Min(x, y)   (x) < (y) ? (x) : (y)  

#define Max(x, y)   (x) < (y) ? (y) : (x)  

#define E(x)        (1 << (x))  

#define iabs(x)     (x) < 0 ? -(x) : (x)  

#define OUT(x)  printf("%I64d\n", x)  

#define lowbit(x)   (x)&(-x)  

#define Read()  freopen("data.in", "r", stdin)  

#define Write() freopen("d.out", "w", stdout)  

   

   

#define M 100007  

#define N 57  

   

using namespace std;  

   

const int inf = 0x7f7f7f7f;  

const int mod = 1000000007;  

   

double dp[N][N];  

double a, b, c, d, e;  

   

int main()  

{  

//    Read();  

    int n;  

    while (~scanf("%d",&n))  

    {  

        if (!n) break;  

        cin>>a>>b>>c>>d>>e;  

        CL(dp,0);  

        dp[n][1] = 0;  

        for (int i = 1; i <= n - 1; ++i)  

        {  

            dp[n][i + 1] += (dp[n][i] + 1);  

        }  

   

        for (int i = n - 1; i >= 1; --i)  

        {  

            dp[i][1] += (dp[i + 1][1] + 1)*a + (dp[i + 1][2] + 1)*b;  

            for (int j = 2; j <= i; ++j)  

            {  

                dp[i][j] += (dp[i + 1][j] + 1)*c + (dp[i + 1][j + 1] + 1)*d + (dp[i][j - 1] + 1)*e;  

            }  

        }  

   

        printf("%.2lf\n",dp[1][1]);  

    }  

    return 0;  

}  
View Code

 

J:Contest Print Server

坑爹的大水题,什么也不说了。

#include <iostream>  

#include <cstdio>  

#include <cmath>  

#include <vector>  

#include <cstring>  

#include <algorithm>  

#include <string>  

#include <set>  

#include <functional>  

#include <numeric>  

#include <sstream>  

#include <stack>  

#include <map>  

#include <queue>  

  

#define CL(arr, val)    memset(arr, val, sizeof(arr))  

  

#define lc l,m,rt<<1  

#define rc m + 1,r,rt<<1|1  

#define pi acos(-1.0)  

#define ll __int64  

#define L(x)    (x) << 1  

#define R(x)    (x) << 1 | 1  

#define MID(l, r)   (l + r) >> 1  

#define Min(x, y)   (x) < (y) ? (x) : (y)  

#define Max(x, y)   (x) < (y) ? (y) : (x)  

#define E(x)        (1 << (x))  

#define iabs(x)     (x) < 0 ? -(x) : (x)  

#define OUT(x)  printf("%I64d\n", x)  

#define lowbit(x)   (x)&(-x)  

#define Read()  freopen("din.txt", "r", stdin)  

#define Write() freopen("dout.txt", "w", stdout);  

  

  

#define M 10007  

#define N 107  

  

using namespace std;  

  

  

const int inf = 0x7f7f7f7f;  

  

  

struct node  

{  

    string name;  

    int pa;  

}nd[N],ans;  

int n,s,x,y,mod;  

string name,num,tmp;  

  

int ToNo(string st)  

{  

    int no = 0;  

    for (int i = 0; i < st.size(); ++i)  

    {  

        no = no*10 + st[i] - '0';  

    }  

    return no;  

}  

int main()  

{  

//    Read();  

    int T;  

    scanf("%d",&T);  

    while (T--)  

    {  

        scanf("%d%d%d%d%d",&n,&s,&x,&y,&mod);  

        for (int i = 0; i < n; ++i)  

        {  

            cin>>name>>tmp>>num>>tmp;  

            nd[i].name = name;  

            nd[i].pa = ToNo(num);  

        }  

        int cnt = 0;  

        for (int i = 0; i < n; ++i)  

        {  

            int tp = cnt + nd[i].pa;  

            if (tp <= s)  

            {  

                cnt += nd[i].pa;  

                ans = nd[i];  

            }  

            else  

            {  

                ans.name = nd[i].name;  

                ans.pa = s - cnt;  

                cnt = 0;  

                s = (s*x + y)%mod;  

                if (s == 0) s = (s*x + y)%mod;  

                i--;  

            }  

            cout<<ans.pa<<" pages "<<"for "<<ans.name<<endl;  

        }  

        cout<<endl;  

    }  

}  
View Code

 

 

你可能感兴趣的:(程序设计)