山东省第四届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 太喜欢质数了以至于他计数也需要用质 ...
随机推荐
- 输入一个网站地址到网站展现的过程以及APR协议(鬼知道中间经历了什么)
以前只知道输入一个网站,然后看着返回琳琅满目的内容,其实中间经历的过程和步骤太多了.为了满足好奇心以及学习需要,特查阅了资料将其记录下来以备后续自己复习. 从我在地址栏输入www.zhihu.com ...
- 310实验室OTL问题(2)
1.PyOptimization代码学习心得 (1).该部分由三个分块组成(按完成的相应的任务).第一部分,运行函数. 以optimization.py为入口程序,其思路是:首先获取路径,然后,初始化 ...
- 【转载】排查Linux机器是否已经被入侵
背景信息:以下情况是在CentOS 6.9的系统中查看的,其它Linux发行版类似 1.入侵者可能会删除机器的日志信息,可以查看日志信息是否还存在或者是否被清空,相关命令示例: [root ...
- POI官网中的例子
官方指南中的例子: http://poi.apache.org/spreadsheet/quick-guide.html#New+Sheet 这一节 Workbook wb = new HSSFWor ...
- Oracle性能优化之Oracle里的执行计划
一.执行计划 执行计划是目标SQL在oracle数据库中具体的执行步骤,oracle用来执行目标SQL语句的具体执行步骤的组合被称为执行计划. 二.如何查看oracle数据库的执行计划 oracle数 ...
- sklearn学习笔记(一)——数据预处理 sklearn.preprocessing
https://blog.csdn.net/zhangyang10d/article/details/53418227 数据预处理 sklearn.preprocessing 标准化 (Standar ...
- Python开发【模块】:内置模块
内置模块 1.__import__ # import app目录下的kingadmin.py文件 for app in conf.settings.INSTALLED_APPS: __import__ ...
- Python开发【Django】:时间处理
时间格式化 做博客后台时,需要经常对数据库里面的时间格式(2017-02-17 02:10:44.308638)进行处理,格式化成自己想要的时间(列如年月日),下面就来记录下如何对时间进行处理 1.时 ...
- 寻找最小(最大)的k个数
题目描述:输入n个整数,输出其中最小的k个元素. 例如:输入1,2,3,4,5,6,7,8这8个数字,则最小的4个数字为1,2,3,4. 思路1:最容易想到的方法:先对这个序列从小到大排序,然后输出前 ...
- 如何在多个LinearLayout中添加分隔线
1.可以放置一个ImageView组件,然后将其设为分隔线的颜色或图形.分隔线View的定义代码如下: 2.在Android3.0及以上版本,LinearLayout支持直接显示分隔线. an ...