7.21test

今天考试了, 考了好几道题

依次为:

矩阵乘法

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 502, mod = 1e9+7;

int n, p, m;
int f1[N][N], f2[N][N];
int f3[N][N];

inline int work (int x, int y) {
   int res = 0;
   for (int i = 1; i <= p; ++ i) {
      res += (f1[x][i]*f2[i][y])%mod;
      res %= mod;
   }
   if (res >= 0) return res%mod;
   if (res < 0) return (res+mod)%mod;
}

main () {
   cin >> n >> p >> m;
   for (int i = 1; i <= n; ++ i)
      for (int j = 1; j <= p; ++ j)
         cin >> f1[i][j];
   for (int i = 1; i <= p; ++ i)
      for (int j = 1; j <= m; ++ j)
	 cin >> f2[i][j];
   for (int i = 1; i <= n; ++ i)
      for (int j = 1; j <= m; ++ j)
	 f3[i][j] = work(i, j);
   for (int i = 1; i <= n; ++ i) {
      for (int j = 1; j <= m; ++ j)
         cout << f3[i][j] << ' ';
      cout << '
';
   }
   return 0;
}

其实这个题特别水,就是没有学过矩阵乘法的人都能做对
说白了就是个模拟,需要注意(long long),还有(res)要边算边模,并且还要判负数

但是我考试的时候,没开(longlong), (res)没有中途取模

就是(zero)了....

大炮

代码:

#include <bits/stdc++.h>
#define int long long
#define mod 2333
using namespace std;

const int N = 6e6;
int n, k, T;
int js[N];

inline int ksm (int a, int b) {
   if (b == 0) return 1%mod;
   if (b&1) return a*ksm(a, b-1)%mod;
   int tmp = ksm(a, b/2)%mod;
   return tmp*tmp%mod;
}

inline int C (int n, int m) {
   if (m > n) return 0;
   return (js[n]*ksm(js[m],mod-2))%mod*ksm(js[n-m], mod-2)%mod;
}

inline int lucas (int n, int m) {
   if (!m) return 1;
   return C (n%mod, m%mod)*lucas(n/mod, m/mod)%mod;
}

inline int calc(int n, int k) {
   int res = 0, t = 0;
   for (int i = 0; i <= k; ++i) {
      t = lucas(n, i)%mod;
      res += t;
      res %= mod;
   }
   return res%mod;
}
signed main() {
   cin >> T;
   while (T-- > 0) {
      cin >> n >> k;
      js[0] = 1;
      for (int i = 1; i <= mod; ++i)
         js[i] = (js[i - 1] * i) % mod;
	 cout << calc(n, k) << '
';
   }
   return 0;
}

这就是一个**数学题,要推式子,但是我不会,看出来是个Lucas但是不会写

这个数据比较**正好卡我百分之五十的数据,也就是说,不动脑子,敲Lucas板子的话,可以拿到百分之五十的数据

但是我就是不会推 也不想去推

这种操蛋数学题,正如郑好学长所言,爱练不练的,考的几率没准,简单的大家都会,难的大家都不会

第三题

(Description)

桌面上有R张红牌和B张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1美元,黑牌则付出1美元。可以随时停止翻牌,在最优策略下平均能得到多少钱。

(Input)

一行输入两个数R,B,其值在0到5000之间

(Output)

在最优策略下平均能得到多少钱

(Sample) (Input)

5 1

(Sample) (Output)

4.166666

(HINT)

输出答案时,小数点后第六位后的全部去掉,不要四舍五入.

代码:

#include <bits/stdc++.h>
#include <cmath>
using namespace std;

const int N = 1e5+66;

double R, B, res;
long long nows;
double f[6][6666];

int main() {
   cin >> R >> B;
   for (int i = 0; i <= R; ++ i, nows ^=1, f[nows][0] = i)
      for (int j = 1; j <= B; ++ j) 
	 f[nows][j] = max(0*1.0, 
	              1.0 * i/(i + j)*(f[nows ^ 1][j]+1)
		      + 1.0 * j/(i + j)*(f[nows][j - 1]-1));
   res = f[nows^1][(int)B];
   long long z = res*10000000;
   long long k = z%10;
   z -= k;
   double ans = (double)z/10000000;
   printf ("%.6lf", ans);
   return 0;
}

这是一道期望dp

(f[i][j])表示选(i)张红的(j)张黑色的答案

卡内存所以需要滚动数组

(f[i][j]) = (max)((0,dfrac{i}{i*j}*(f[i-1][j]+1)+dfrac{j}{i*j}*(f[i][j-1]-1)))

奶牛去搬砖

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5+66, INF = 214748364;

priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
struct edge {int to, nxt, val;}e[N]; int cnt, head[N];

int n, S, E;
int dis[N], tag[N];

inline void add (int u, int v, int w) {
   e[++cnt].nxt = head[u]; head[u] = cnt;
   e[cnt].to = v;
   e[cnt].val = w;
}

inline void dij () {
   for (int i = S; i <= E+6; ++ i) dis[i] = INF;
      dis[S] = 0, q.push(make_pair(0, S));
      while (q.size()) {
	 int x = q.top().second; q.pop();
	 if (tag[x]) continue; tag[x] = 1;
	    for (int i = head[x]; i; i = e[i].nxt) {
	       int y = e[i].to;
	       if (dis[y] > dis[x]+e[i].val){
		  dis[y] = dis[x]+e[i].val, dis[y];
		  q.push(make_pair(dis[y], y));
	       }
	    }
      }
}

int main () {
   cin >> n >> S >> E;
   for (int i = S; i <= E; ++ i) add(i+1, i, 0);
   for (int i = 1; i <= n; ++ i) {
      int u, v, w;
      cin >> u >> v >> w;
      if (u < S) u = S;
      if (v > E) v = E;
      add(u, v+1, w);
   }
   dij();
   if (dis[E+1] == INF) puts ("-1");
   else cout << dis[E+1];
   return 0;
}

建个图,跑一跑,完事。可是考试时候的我,连题目都没看懂什么意思(英文题面, 教练给翻译了,但是感觉那个翻译看起来很不爽,索性没有做)

但是这个题真的很简单,就是需要一步很巧妙的回退思想
(add(i+1, i, 0)):建一条权值为零的回退的边

1 3

4 5

虽然没有交集,但是上述情况是可以满足题意的

所以建边的时候要(add(u,v+1,w))

单位错选

#include <bits/stdc++.h>
using namespace std;

const int N = 1e7+10;

int n, A, B, C, tmp;
int a[N];

double res;

int main () {
   scanf("%d%d%d%d%d", &n, &A, &B, &C, a + 1);
   for (int i = 2; i <= n; i++)
      a[i] = ((long long) a[i - 1] * A + B) % 100000001;
   for (int i = 1; i <= n; i++)
      a[i] = a[i] % C + 1;
   res += 1.0*min(a[1], a[n])/a[1]/a[n];
   for (int i = 1; i < n; ++ i) res += 1.0*min(a[i], a[i + 1])/a[i]/a[i + 1];
   printf ("%.3lf", res);
   return 0;
}

假设第(i)个题目的选项数是(a[i]),那么(gx)做对这道题目的概率就是(dfrac{min(a[i],a[i-1])}{a[i]*a[j]})

(i == 1)的时候特判 然后把每个题做对的概率加起来就好了

其实说实话,我还是感觉不太理解 也说不出来哪里不明白

可能是初次接触概率的题吧,这是个锅,以后得补上

互相伤害

#include <bits/stdc++.h>
using namespace std;

const int N = 666;

int n, k;
long long f[10][N][N], res;

inline int self (int x) {
   if ((x&(x<<1)) || (x&(x>>1))) return false;
   return true;
}

inline int Double (int x, int y) {
   if ((x&(y<<1)) || (x&(y>>1) || (x&y))) return false;
   return true;
}

inline int work (int x) {
   int nows(0);
   while (x) {if (x&1) ++ nows; x >>= 1;}
   return nows;
}

signed main () {
   scanf ("%d%d", &n, &k);
   f[0][0][0] = 1;
   for (int i = 1; i <= n; ++ i) {
      for (int j = 0; j < (1<<n); ++ j) {
         if (self (j)) {
            for (int z = 0; z < (1<<n); ++ z) {
	       if (self(z) && Double(z, j)) {
		  for (int len = 0; len <= k; ++ len) {
		      int nx = work(j), ny = work(z);
		      if (nx+ny>len) continue;
		      f[i][j][len] += f[i-1][z][len-nx];
		  }
               }
            }
         }
      }
   }
   for (int i = 0; i < (1<<n); ++ i) res += f[n][i][k];
   cout << res;
   return 0;
}

状压dp

(f[i][j][k])表示我们当前摆放棋子摆到了第(i)行的时候(包括前(i)行)当前第(i)行的状态为(j),并且一共用了(k)个国王所呈现出的方案数

又因为i行之前的状态方案数都是互不影响的,所以说,是“或”的关系,根据加法原理,可以直接相加

所以转移方程可以写出来:

(f[i][j][k] += f[i-1][z][k-Work(j)])

自此所有题目分析完毕


(7.28update)

关于第二题大炮,看了看题解,还是不会推

给出ac代码

// da pao
#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 3e3, p = 2333;

int n, m, T;
int c[N][N], f[N][N];

inline int Lucas (int n, int m) {
   if (!m || n == m) return 1;
   if (n < m) return 0;
   return Lucas(n/p, m/p)*c[n%p][m%p]%p;
}	

inline int calc (int n, int m) {
   if (m == -1) return 0;
   if (!m) return 1;
   if (n < p) return f[n][m];
   return (f[n%p][n%p]*calc(n/p,m/p-1)+Lucas(n/p,m/p)*f[n%p][min(n%p, m%p)])%p;
}
inline void yuchuli() {
   c[0][0] = f[0][0] = 1;
   for (int i = 1; i <= p; ++ i) {
      f[i][0] = c[i][0] = c[i][i] = 1;
      for (int j = 1; j <= i-1; ++ j)
	 c[i][j] = (c[i - 1][j] + c[i - 1][j - 1])%p;
         for (int j = 1; j <= p; ++ j)
	 f[i][j] = (f[i][j - 1] + c[i][j])%p;
   }
}	
	
inline void caozuoyixia () {
   scanf ("%lld%lld", &n, &m);
   cout << calc(n, m) << '
';
}	
	
signed main () {
   yuchuli();
   cin >> T;
   while (T --> 0) caozuoyixia();
   return 0;
}
原文地址:https://www.cnblogs.com/yszhyhm/p/13365619.html