山东省第四届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

 

 

posted @ 2013-06-18 21:46  E_star  阅读(765)  评论(0编辑  收藏  举报