【11/3】模拟赛

第一题 方程

【题目描述】

给出非负整数N,统计不定方程x + y ^ 2 + z ^ 3 = n的非负整数解(x,y,z)的数量。

 

【输入格式】

一行一个数N。

 

【输出格式】

解得数量。

  

【样例输入】

5

 

【样例输出】

 

【数据范围】

N <= 10 ^ 16。

 

【分析】

首先枚举Z。因为Z可取的范围是最小的。然后剩下的n – z ^ 3设为t。将t开方。向下取整得到的就是在当前z的取值下最大的y的取值。因为随着y的减小x在增大,所以y的最小值就是0。当前z的取值下解的个数就是y的最大值加1(包括0)。

考试时想到了枚举z,然后找到y的最大值。但是没有想到x取0时y有最大值可以直接开方取整的做法。打了两个表二分查找。不过倒是得到了60%的数据。

 

第二题 方程式

【题目描述】

给出一个字符串,表达一个方程。保证里面系数不会超过1000000000。保证方程偶且只有一个解,而且方程只会有一个未知数X,且X的最高指数也只会有1。

方程中所有的系数都是整数,且系数是1就会被忽略。

只会出现加减,不会出现乘除。

 

【输入格式】

输入一个字符串。表示方程。

 

【输出格式】

输出X的解。保留三位小数。

 

【样例输入】

6x+7x+8x+1=6x+7x+9x

 

【样例输出】

1.000

 

【数据范围】

100%方程长度不会超过255。

 

【分析】

四道题里最简单的模拟。注意x前面的系数是0的情况(虽然这有点不符合常理)。

 

第三题 Muti

【题目描述】

a1b1 + a2b2 + a3b3 + … + anbn = c这个式子是给出的。且给出c还有a1一直到an(全是正整数)。求出b1到bn到底有多少组非负整数解。

 

【输入格式】

第一行:n和c。

第二行n个数分别表示a1到an。

 

【输出格式】

输出总解数(用99983取模)。

 

【样例输入】

2 4

1 2

 

【样例输出】

3

 

【数据范围】

n <= 100,c <= 100000。

 

【分析】

模型:N个物体。ai是第i个物体的价值。bi是第i个物体取的个数。问多少种方法可以凑成c。动归过程:

for (int i = 1;i <= n;++i)

  for (int j = a[i];j <= c;++j)

    f[j] += f[j – a[i]];

 

第四题 交错匹配

【题目描述】

有两排非负整数,A[1…N],B[1…M],如果 A[i]=B[j]=K,那么可以在 A[i],B[j]之间 连一条线,称为一条K 匹配

,每个数至多连一条线。另外,每个K 匹配都必须跟一个 L匹 配相交且K≠L!现在要求一个最大的匹配数。例如:

以下两行数的最大匹配数为 8。一个数最多只能和一个数连线。

 

【输入格式】

第一行包含两个正整数 N 和M。 
第二行 N个自然数表示 A[i]。 
第三行 M 个自然数表示 B[i]。
 
【输出格式】
只有一个数字,即最大匹配数。 
  
【样例输入】
样例输入1 样例输入2
12 11 

1 2 3 3 2 4 1 5 1 3 5 10 

3 1 2 3 2 4 12 1 5 5 3 
4 4 

1 1 3 3 

1 1 3 3 

 

【样例输入】

样例输入1 样例输入2
8 0

 

【分析】

一下为引用dream的题解(有删减)。原文链接:http://ren.meng.meng.blog.163.com/blog/static/2337029720081010419447/

  1. 首先应该是一条匹配线能且只能与一条相交
  2. 从末状态出发,想方设法缩小要求解的问题。这个需要一点巧妙的思想,头脑清晰时应该可以想出来g[i,j]表示上行a:i个和下行不:j个的最大匹配数,如果要缩小问题的话,可以考虑i-1或j-1,这样就要分情况,也就是所谓的从各个子问题中找一个最优的,这时要做到“不重不漏”。。具体这个问题:g[i,j]:当从a[i]不引线时,g[i,j]=g[i-1,j];(这里包括从b[j]引线和不从b[j]引线两种情况 ,但这个问题是g[i-1,j]需要解决的,所以这里就有了很重要的一点技巧,就是学会“推卸责任”,也就是说要运用子问题这个优势,不要把缩小问题这一步变成全盘考虑所有问题〔枚举〕)当从b[j]不引线时,g[i,j]=g[i,j-1];当从a[i]和b[j]各引一条线时,他俩必然匹配。设a[i]与b[v]匹配,b[j]与a[u]匹配,则g[i,j]=g[u-1,v-1]+2;这样便完美地缩小了所求问题。
  3. 另外还要建树组v[i,j]和u[i,j],这就是所谓的2次动态规划(应该是第0次),u和v应该要分开求吧~

 

代码

第一题

#include <stdio.h>

#include <math.h>

long long n,x,y,z,ans,tem;

int main() {

  freopen("equation.in","r",stdin);

  freopen("equation.out","w",stdout);

  scanf("%lld",&n);

  for (z = 0;z <= 215443;++z) {

    if (z * z * z > n)

      break;

    tem = (long long)sqrt(n - z * z * z);

    ans += tem + 1;

  }

  printf("%lld\n",ans);

  return 0;

}



第二题

#include <stdio.h>

#include <ctype.h>

#include <string.h>

#define MAXN 300

char s[MAXN];

double xx,yy;

long long len,x,y,wh;

bool jia;

int main() {

  freopen("equationagain.in","r",stdin);

  freopen("equationagain.out","w",stdout);

  scanf("%s",s);

  len = strlen(s);

  for (int i = 0;i < len;++i)

    if (s[i] == '=') {

      wh = i;

      break;

    }

  jia = 1;

  for (int i = 0;i < wh;++i)

    if (isdigit(s[i]))

      x = x * 10 + s[i] - '0';

    else

      if (s[i] == 'x') {

        if (!x) {

          x = 1;

          if ((i) && (s[i - 1] == '0'))

            x = 0;

        }

        if (jia)

          xx += x;

        else

          xx -= x;

        x = 0;

      } else {

          if (x) {

            if (jia)

              yy -= x;

            else

              yy += x;

            x = 0;

          }

          if (s[i] == '+')

            jia = 1;

          else

            jia = 0;

        }

  if (x) {

    if (jia)

      yy -= x;

    else

      yy += x;

    x = 0;

  }

  jia = 1;

  for (int i = wh + 1;i < len;++i)

    if (isdigit(s[i]))

      x = x * 10 + s[i] - '0';

    else

      if (s[i] == 'x') {

        if (!x) {

          x = 1;

          if ((i) && (s[i - 1] == '0'))

            x = 0;

        }

        if (jia)

          xx -= x;

        else

          xx += x;

        x = 0;

      } else {

          if (x) {

            if (jia)

              yy += x;

            else

              yy -= x;

            x = 0;

          }

          if (s[i] == '+')

            jia = 1;

          else

            jia = 0;

        }

  if (x) {

    if (jia)

      yy += x;

    else

      yy -= x;

    x = 0;

  }

  xx = yy / xx;

  printf("%.3lf\n",xx);

  return 0;

}



第三题

#include <stdio.h>

#define MAXN 11

#define MAXC 100010

#define mmm 999983

int a,f[MAXC];

int n,c;

int main() {

  freopen("muti.in","r",stdin);

  freopen("muti.out","w",stdout);

  scanf("%d%d",&n,&c);

  f[0] = 1;

  for (int i = 1;i <= n;++i) {

    scanf("%d",&a);

    for (int j = a;j <= c;++j) {

      f[j] += f[j - a];

      f[j] %= mmm;

    }

  }

  printf("%d\n",f[c]);

  return 0;

}

  

第四题

#include <stdio.h>

#include <iostream>

#define MAXN 1010

using namespace std;

int f[MAXN][MAXN],a[MAXN],b[MAXN],u[MAXN][MAXN],d[MAXN][MAXN];

int n,m;

int main() {

  freopen("cross.in","r",stdin);

  freopen("cross.out","w",stdout);

  scanf("%d%d",&n,&m);

  for (int i = 1;i <= n;++i)

    scanf("%d",&a[i]);

  for (int i = 1;i <= m;++i)

    scanf("%d",&b[i]);

  for (int i = 1;i <= n;++i)

    for (int j = 1;j <= m;++j)

      if ((j > 1) && (b[j - 1] == a[i]))

        u[i][j] = j - 1;

      else

        u[i][j] = u[i][j - 1];

  for (int j = 1;j <= m;++j)

    for (int i = 1;i <= n;++i)

      if ((i > 1) && (a[i - 1] == b[j]))

        d[j][i] = i - 1;

      else

        d[j][i] = d[j][i - 1];

  for (int i = 1;i <= n;++i)

    for (int j = 1;j <= m;++j) {

      f[i][j] = max(f[i - 1][j],f[i][j - 1]);

      if (a[i] != b[j]) {

        int l,r;

        l = d[j][i];

        r = u[i][j];

        if ((l > 0) && (r > 0) && (f[l - 1][r - 1] + 2 > f[i][j]))

          f[i][j] = f[l - 1][r - 1] + 2;

      }

    }

  printf("%d\n",f[n][m]);

  return 0;

}




你可能感兴趣的:(模拟)