山东省第四届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 = 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; }
题意:
给定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; }
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; }
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 = 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; }
题意:
给出一个多项式:(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; }
题意:
给出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; }
题意:
给你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; }
有没有更优的解法,当然有。 我们回到二维树状数组,如果我们求一个矩阵内的和的话,需要知道四个点到源点的的和,然后根据简单的容斥弄出来。这里我们将每个询问离线处理,转化成四个点,然后将点按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; }
题意:
迷宫是由一个如下的图形组成
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; }
坑爹的大水题,什么也不说了。
#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; } }