山东省第四届ACM程序设计竞赛部分题解
题意:
给你平面上的两个点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 = ;
- 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 ;
- }
题意:
给定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 = ;
- 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 = ; 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 != -; 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 = ;
- while (T--)
- {
- scanf("%d%d",&n,&m);
- CL(head,-); ct = ;
- int x,y;
- for (i = ; i < m; ++i)
- {
- scanf("%d%d",&x,&y);
- add(x,y);
- }
- CL(ok,false);
- for (i = ; i <= n; ++i) ok[i][i] = true;
- for (i = ; i <= n; ++i) bfs(i);
- bool flag = false;
- for (i = ; i <= n && !flag; ++i)
- {
- for (j = ; 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 ;
- }
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 = ;
- ll powB[M + ];
- ll powA[N + ];
- ll n, A, K, a, b, m, P;
- void init()
- {
- powA[] = ;
- for (int i = ; i <= N; ++i)
- {
- powA[i] = powA[i - ]*A%P;
- }
- ll tmp = powA[N];
- powB[] = ;
- for (int i = ; i <= M; ++i)
- {
- powB[i] = powB[i - ]*tmp%P;
- }
- }
- void solve(int cas)
- {
- ll fx = K;
- ll ans = ;
- for (int i = ; 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 = ;
- scanf("%d",&T);
- while (T--)
- {
- cin>>n>>A>>K>>a>>b>>m>>P;
- init();
- solve(cas++);
- }
- return ;
- }
D: Rubik’s cube
好像是个模拟题,还没写
题意:
给你一个长度为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 = ;
- int dp[],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 = ; i < n; ++i) s[i] = ts[i] - 'a';
- CL(dp,); CL(dl,); CL(dr,);
- for (i = ; i < n; ++i)
- {
- for (j = ; j < s[i]; ++j) dl[i] += dp[j];
- dl[i] %= ;
- dp[s[i]] += (dl[i] + );
- dp[s[i]] %= ;
- }
- CL(dp,);
- for (i = n - ; i >= ; --i)
- {
- for (j = ; j < s[i]; ++j) dr[i] += dp[j];
- dr[i] %= ;
- dp[s[i]] += (dr[i] + );
- dp[s[i]] %= ;
- }
- int ans = ;
- for (i = ; i < n; ++i)
- {
- ans += dl[i]*dr[i];
- ans %= ;
- }
- printf("%d\n",ans);
- }
- return ;
- }
题意:
给出一个多项式:(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 = ;
- int a[N],b[];
- int main()
- {
- int T,i;
- int n,m;
- scanf("%d",&T);
- while (T--)
- {
- scanf("%d",&n);
- CL(a,);
- for (i = ; i < n; ++i) scanf("%d",&a[i]);
- scanf("%d",&m);
- int top;
- ll p;
- while (m--)
- {
- cin>>p; top = ;
- if (p == )
- {
- printf("1\n");
- continue;
- }
- while (p)
- {
- b[top++] = p%;
- p /= ;
- }
- int ans = ;
- for (i = ; i < top; ++i)
- {
- if (b[i]) ans = ans*a[i]%;
- }
- printf("%d\n",ans);
- }
- }
- return ;
- }
题意:
给出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 = ;
- const ll R = ((1uLL<<) - );
- ll dp[][][];
- int bit[];
- ll n;
- ll dfs(int len,int pre,int flag,int limit)
- {
- if (len == -) return flag||pre == ;
- if (!limit && dp[len][pre][flag] != -1uLL) return dp[len][pre][flag];
- int up = limit?bit[len]:;
- ll ans = ;
- for (int i = ; i <= up; ++i)
- {
- int tpre = (pre* + i)%;
- int tflag = (flag || i == );
- int tlimit = (limit && i == up);
- ans += dfs(len - ,tpre,tflag,tlimit);
- }
- if (!limit) dp[len][pre][flag] = ans;
- return ans;
- }
- ll getR(ll m)
- {
- int len = ;
- while (m)
- {
- bit[len++] = m%;
- m /= ;
- }
- return dfs(len - ,,,) - ;
- }
- ll solve(ll m)
- {
- ll cnt1 = getR(m);
- ll cnt2 = cnt1 - getR(cnt1);
- return cnt2;
- }
- int main()
- {
- // Read();
- while (~scanf("%lld",&n))
- {
- CL(dp,-);
- ll l = ,r = R;
- ll ans = ;
- while (l <= r)
- {
- ll mid = (l + r)>>;
- if (solve(mid) < n) l = mid + ;
- else
- {
- ans = mid;
- r = mid - ;
- }
- }
- printf("%lld\n",ans);
- }
- return ;
- }
题意:
给你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)>>;
- }
- }tt[N<<];
- int toLeft[][N];
- int val[][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 + ;
- for (i = l; i <= r; ++i){
- if (val[d][i] < sorted[m]) lsame--;
- }
- int lpos = l;
- int rpos = m + ;
- int same = ;
- for (i = l; i <= r; ++i){
- if (i == l) toLeft[d][i] = ;
- else toLeft[d][i] = toLeft[d][i - ];
- if (val[d][i] < sorted[m]){
- toLeft[d][i]++;
- val[d + ][lpos++] = val[d][i];
- }
- else if (val[d][i] > sorted[m]){
- val[d + ][rpos++] = val[d][i];
- }
- else{
- if (same < lsame){
- toLeft[d][i]++;
- val[d + ][lpos++] = val[d][i];
- same++;
- }
- else{
- val[d + ][rpos++] = val[d][i];
- }
- }
- }
- build(lc,d + );
- build(rc,d + );
- }
- int query(int L,int R,int k,int d,int rt){
- if (L == R){
- return val[d][L];
- }
- int s = ;
- int ss = ;
- if (L == tt[rt].l){
- ss = ;
- s = toLeft[d][R];
- }
- else{
- ss = toLeft[d][L - ];
- s = toLeft[d][R] - toLeft[d][L - ];
- }
- if (k <= s){
- int newl = tt[rt].l + ss;
- int newr = newl + s - ;
- return query(newl,newr,k,d + ,rt<<);
- }
- else{
- int m = tt[rt].mid();
- int bb = L - tt[rt].l - ss;
- int b = R - L + - s;
- int newl = m + bb + ;
- int newr = newl + b - ;
- return query(newl,newr,k - s,d + ,rt<<|);
- }
- }
- int BS1(int L,int R,int l,int r,int A)
- {
- int ans = -;
- while (l <= r)
- {
- int mid = (l + r)>>;
- int res = query(L,R,mid,,);
- if (res >= A)
- {
- ans = mid;
- r = mid - ;
- }
- else l = mid + ;
- }
- return ans;
- }
- int BS2(int L,int R,int l,int r,int B)
- {
- int ans = ;
- while (l <= r)
- {
- int mid = (l + r)>>;
- int res = query(L,R,mid,,);
- if (res > B)
- {
- ans = mid;
- r = mid - ;
- }
- else l = mid + ;
- }
- if (ans == ) return r;
- else return ans - ;
- }
- int main()
- {
- // Read();
- int T,i;
- int cas = ;
- scanf("%d",&T);
- while (T--)
- {
- scanf("%d%d",&n,&m);
- for (i = ; i <= n; ++i)
- {
- scanf("%d",&val[][i]);
- sorted[i] = val[][i];
- }
- sort(sorted + ,sorted + + n);
- build(,n,,);
- printf("Case #%d:\n",cas++);
- int x,y,A,B;
- while (m--)
- {
- scanf("%d%d%d%d",&x,&y,&A,&B);
- int l = ;
- int r = y - x + ;
- 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 == -)
- {
- printf("0\n");
- continue;
- }
- printf("%d\n",cnt2 - cnt1 + );
- }
- }
- return ;
- }
有没有更优的解法,当然有。 我们回到二维树状数组,如果我们求一个矩阵内的和的话,需要知道四个点到源点的的和,然后根据简单的容斥弄出来。这里我们将每个询问离线处理,转化成四个点,然后将点按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[*N];
- int SM[*N];
- int n,m;
- int c[*N],a[N],b[*N];
- int of[N*][];
- 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 = ;
- while (pos > )
- {
- sum += c[pos];
- pos -= lowbit(pos);
- }
- return sum;
- }
- int BS(int l,int r,int val)
- {
- while (l <= r)
- {
- int mid = (l + r)/;
- if (b[mid] == val) return mid;
- else if (b[mid] < val) l = mid + ;
- else r = mid - ;
- }
- return -;
- }
- 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 = ;
- scanf("%d",&T);
- while (T--)
- {
- scanf("%d%d",&n,&m);
- int k = ;
- for (i = ; i <= n; ++i)
- {
- scanf("%d",&a[i]);
- b[++k] = a[i];
- }
- int pl = ;
- int x1,y1,x2,y2;
- for (i = ; i <= m; ++i)
- {
- scanf("%d%d%d%d",&x1,&x2,&y1,&y2);
- b[++k] = y1 - ; b[++k] = y2;
- pt[pl].x = x1 - , pt[pl].y = y1 - ;
- pt[pl].id = i,pt[pl++].no = ;
- pt[pl].x = x1 - , pt[pl].y = y2;
- pt[pl].id = i,pt[pl++].no = ;
- pt[pl].x = x2, pt[pl].y = y1 - ;
- pt[pl].id = i,pt[pl++].no = ;
- pt[pl].x = x2, pt[pl].y = y2;
- pt[pl].id = i,pt[pl++].no = ;
- }
- sort(b + ,b + + k,cmp); nn = ;
- for (i = ; i <= k; ++i) if (b[i] != b[i - ]) b[++nn] = b[i];
- sort(pt,pt + pl,cmpPt);
- for (i = ; i < pl; ++i) of[pt[i].id][pt[i].no] = i;
- CL(c,); CL(ans,);
- int s = ;
- for (i = ; i < pl; ++i)
- {
- int x = pt[i].x;
- int y = pt[i].y;
- for (; s <= x; ++s)
- {
- int pos = BS(,nn,a[s]);
- modify(pos,);
- }
- int p = BS(,nn,y);
- SM[i] = getsum(p);
- if (pt[i].no == )
- {
- int id = pt[i].id;
- ans[id] = SM[i] - SM[of[id][]] - SM[of[id][]] + SM[of[id][]];
- }
- }
- printf("Case #%d:\n",cas++);
- for (i = ; i <= m; ++i) printf("%d\n",ans[i]);
- }
- return ;
- }
题意:
迷宫是由一个如下的图形组成
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 = ;
- 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,);
- dp[n][] = ;
- for (int i = ; i <= n - ; ++i)
- {
- dp[n][i + ] += (dp[n][i] + );
- }
- for (int i = n - ; i >= ; --i)
- {
- dp[i][] += (dp[i + ][] + )*a + (dp[i + ][] + )*b;
- for (int j = ; j <= i; ++j)
- {
- dp[i][j] += (dp[i + ][j] + )*c + (dp[i + ][j + ] + )*d + (dp[i][j - ] + )*e;
- }
- }
- printf("%.2lf\n",dp[][]);
- }
- return ;
- }
坑爹的大水题,什么也不说了。
- #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 = ;
- for (int i = ; i < st.size(); ++i)
- {
- no = no* + st[i] - '';
- }
- 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 = ; i < n; ++i)
- {
- cin>>name>>tmp>>num>>tmp;
- nd[i].name = name;
- nd[i].pa = ToNo(num);
- }
- int cnt = ;
- for (int i = ; 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 = ;
- s = (s*x + y)%mod;
- if (s == ) s = (s*x + y)%mod;
- i--;
- }
- cout<<ans.pa<<" pages "<<"for "<<ans.name<<endl;
- }
- cout<<endl;
- }
- }
山东省第四届ACM程序设计竞赛部分题解的更多相关文章
- UPC 2224 Boring Counting ★(山东省第四届ACM程序设计竞赛 tag:线段树)
[题意]给定一个长度为N的数列,M个询问区间[L,R]内大于等于A小于等于B的数的个数. [题目链接]http://acm.upc.edu.cn/problem.php?id=2224 省赛的时候脑抽 ...
- 山东省第四届ACM程序设计竞赛A题:Rescue The Princess
Description Several days ago, a beast caught a beautiful princess and the princess was put in prison ...
- 山东省第四届ACM程序设计竞赛A题:Rescue The Princess(数学+计算几何)
Rescue The Princess Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 412 Solved: 168[Submit][Status][ ...
- 浙江省第十六届大学生ACM程序设计竞赛部分题解
E .Sequence in the Pocket sol:将数组copy一份,然后sort一下,找寻后面最多多少个元素在原数组中保持有序,用总个数减去已经有序的就是我们需要移动的次数. 思维题 #i ...
- 山东省第四届ACM大学生程序设计竞赛解题报告(部分)
2013年"浪潮杯"山东省第四届ACM大学生程序设计竞赛排名:http://acm.upc.edu.cn/ranklist/ 一.第J题坑爹大水题,模拟一下就行了 J:Contes ...
- Alice and Bob(2013年山东省第四届ACM大学生程序设计竞赛)
Alice and Bob Time Limit: 1000ms Memory limit: 65536K 题目描述 Alice and Bob like playing games very m ...
- 2013年山东省第四届ACM大学生程序设计竞赛-最后一道大水题:Contest Print Server
点击打开链接 2226: Contest Print Server Time Limit: 1 Sec Memory Limit: 128 MB Submit: 53 Solved: 18 [Su ...
- sdut Mountain Subsequences 2013年山东省第四届ACM大学生程序设计竞赛
Mountain Subsequences 题目描述 Coco is a beautiful ACMer girl living in a very beautiful mountain. There ...
- 华南师大 2017 年 ACM 程序设计竞赛新生初赛题解
题解 被你们虐了千百遍的题目和 OJ 也很累的,也想要休息,所以你们别想了,行行好放过它们,我们来看题解吧... A. 诡异的计数法 Description cgy 太喜欢质数了以至于他计数也需要用质 ...
随机推荐
- hdu4975 网络流解方程组(网络流+dfs判环或矩阵DP)
http://acm.hdu.edu.cn/showproblem.php?pid=4975 A simple Gaussian elimination problem. Time Limit: 20 ...
- SQL取某个字符串最后一次出现的位置后面的字符串方法
--sql怎么取某个字符串最后一次出现的位置后面的字符串 declare @s varchar(max); set @s = 'fj/2016815/2016081553677565.pdf'; se ...
- MacBook鼠标指针乱窜/不受控制问题的解决方法
用了快一年的MacBook Pro最近出现了奇怪的问题.出问题时,鼠标不受控制,屏幕上鼠标指针乱窜,还时不时自动点击,犹如电脑被人远程控制一般.不管是用trackpad还是用外接鼠标,都是同样问题.电 ...
- python基础之练习题(二)
九九乘法表 i = 0 #while 九九乘法表 j = 0 while i < 9: i += 1 while j<9: j += 1 sum = i + j total="% ...
- 【mlflow】mlflow打包、启动、换用mysql backend、mysql配置
mlflow是一个自动化机器学习平台,支持python2也支持python3 mlflow9.0添加了数据库作为tracking data的存储: https://github.com/mlflow/ ...
- 浅谈Java中的equals和==(转载)
在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str2 = new String(&qu ...
- 洛谷P3939 数颜色 二分查找
正解:二分 解题报告: 传送门! 话说其实我开始看到这题想到的是分块,,, 但是显然不用这么复杂,,,因为仔细看下这题,会发现每次只改变相邻的兔子的位置 所以开个vector(或者开个数组也成QwQ( ...
- centos 目录结构 快捷键 ls命令,alias别名,so:动态库 a:静态库,环境变量PATH,Ctrl+z 暂停命令,Ctrl+a 光标到行首,Ctrl+e 光标到行尾,Ctrl+u 删除光标前所有字符 Ctrl+r 搜索命 hash命令 Ctrl+左箭头/右箭头 cd命令 第三节课
centos 目录结构 快捷键 ls命令,alias别名,so:动态库 a:静态库,环境变量PATH,Ctrl+z 暂停命令,Ctrl+a 光标到行首,Ctrl+e 光标到行尾,Ctrl+u 删除光标 ...
- Hadoop集群完全分布式坏境搭建
前言 上一篇我们讲解了Hadoop单节点的安装,并且已经通过VMware安装了一台CentOS 6.8的Linux系统,咱们本篇的目标就是要配置一个真正的完全分布式的Hadoop集群,闲言少叙,进入本 ...
- 微软官方推出的win10安装或者创建安装u盘的工具
https://www.microsoft.com/zh-cn/software-download/windows10 下载安装后,可根据提示,一步步的安装win10或者创建安装u盘