小灶第四次作业:周赛补题

比较失败的一次比赛,第二道题wa了n次之后就被叫走干活。。。一道题手动垫底了。。。。

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=112449#problem

A:重新定义 Fibonacci  F(0) = 7, F(1) = 11, F(n) = F(n-1) + F(n-2) (n>=2).     Print the word "yes" if 3 divide evenly into F(n). Print the word "no" if not.

第六感比较准确直接选择找规律,因为只需要看是否会被3整除,所以结果应该是循环的,事实证明以4为周期。。。

#include <iostream>
#include <cstdio>
#define maxn 1e7
using namespace std;

int main()
{
    int n ;
    while (scanf("%d",&n) != EOF)
    {
            int  ans = n % 4;
            if(ans == 2 )
                printf("yes\n");
            else
                printf("no\n");

    }
    return 0;

b看懂题是个问题

c:约瑟夫问题变形,前k个好人需要在后k个坏人全部死之后留下来,数组成环的问题,假期的时候卡死,直接跳过,现在看看感觉没有当时想的那么难,时间限制需要打表,k只有14个,数组成环的问题最好还是从1到n,不容易懵逼,假设第j个人要被杀死,则

m = (m %st) ? m%st : st;

表示第m个人将在这轮被杀死,如果m小于k就循环下一个j。

#include <cstdio>
#include <iostream>
int a[15];

int main()
{
    int k;
    for (int k = 1; k <= 13 ;k++)
    {
        int n = 2 * k;
        int flag = 0;

        for (int j = k+1 ; ; j++)
        {
            int m , st = n;
            if(flag)
                break;
            for (int  m = j;;m+=j-1)
            {
                m = (m %st) ? m%st : st;
                if(m <= k)
                    break;
                st--;
                if(st == k)
                {
                    flag = 1;
                    a[k] = j;
                    break;
                }
            }
        }

    }
          while(  scanf("%d",&k) != EOF,k)
            printf("%d\n",a[k]);

}
D:滑雪。。。坑死坑死,说是dp不如说dfs加个状态方程,wa了5发。。。找了2个多小时,蠢得把maxx开在全局变量了,这样每次都会覆盖之前的值,巧合的是过了很多自己写的数据。。。

#include <cstdio>
#include <iostream>
#define maxn 110
int a[maxn][maxn];
int book[maxn][maxn],dir[4][2] = { {0,1}, {0,-1},{1,0},{-1,0} };
int ans;
int row,col;

using namespace std;

void dp(int i, int j)
{
    if(book[i][j])
        return ;
    book[i][j]++;
    int maxx = 0;
    for (int k = 0 ; k < 4 ; k++)
    {
        int x,y;
        x = i + dir[k][0];
        y = j + dir[k][1];
        if(x >= 0 && y >= 0 && x < row && y < col && a[x][y] > a[i][j])
        {
            dp(x,y);
            if(book[x][y]+1 > maxx)
            {
                book[i][j] = book[x][y] +1;
                maxx = book[x][y] +1;
           //     cout << i << "  " << j <<"  "  << book[i][j]<<endl;
            }
        }

    }
}

int main()
{

    scanf("%d%d",&row,&col);

    for (int i = 0 ; i < row ; i++)
        for (int j = 0 ; j < col ; j++)
            scanf("%d",&a[i][j]);
    for (int i = 0 ; i < row ; i++)
        for (int j = 0 ; j < col ; j++)
            dp(i,j);

    int ma = 0;
    for (int i = 0 ; i < row ; i++)
        for (int j = 0 ; j < col ; j++)
            if(book[i][j] > ma)
                ma = book[i][j];
        printf("%d\n",ma);
}
循环的次数写了好几遍,可以改成int返回可以省下来一些

#include <cstdio>
#include <iostream>
#include <cstring>
#define maxn 110
int a[maxn][maxn];
int book[maxn][maxn],dir[4][2] = { {0,1}, {0,-1},{1,0},{-1,0} };
int ans;
int row,col;

using namespace std;

int dp(int i, int j)
{
    if(book[i][j])
        return book[i][j];

   int  maxx = 0;
    for (int k = 0 ; k < 4 ; k++)
    {
        int x,y;
        x = i + dir[k][0];
        y = j + dir[k][1];
        if(x >= 0 && y >= 0 && x < row && y < col && a[x][y] > a[i][j])
        {
            int ans = dp(x,y);
            if(ans  >= maxx)
                maxx = ans;
        }
    }
    book[i][j] = maxx + 1;
    return book[i][j];
}

int main()
{

    while( scanf("%d%d",&row,&col) != EOF)
    {
        memset(a,0,sizeof(a));
        memset(book,0,sizeof(book));
        int m = -1;
    for (int i = 0 ; i < row ; i++)
        for (int j = 0 ; j < col ; j++)
            scanf("%d",&a[i][j]);
    for (int i = 0 ; i < row ; i++)
        for (int j = 0 ; j < col ; j++)
            if(m < dp(i,j))
                m = dp(i,j);

        printf("%d\n",m);
    }
}
E:正常的暴力会tle,然后线段树改区间找节点又不会,借鉴了一个偷懒的方法,每次在左边界a[left]++,右边界的下一个a[right+1]--,设置一个sum,输出的是sum+=a[i],相当于每次从左边界到后面的都+1(因为sum+1了),而过了右边界又减了回来,还是很巧妙的。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
int a[100010];
int main()
{
    int n;
    while (scanf("%d",&n) != EOF,n)
    {
        memset(a,0,sizeof(a));
        for(int i = 0 ; i < n ;i++)
        {
            int r,l;
            scanf("%d%d",&l,&r);
            a[l]++;
            a[r+1]--;
        }
        int sum = 0;
        for (int i = 1; i <= n ;i++)
            printf("%d%c",sum+=a[i],(i==n )?'\n':' ');
    }
}
F:小木棍长度重量都比下一个大的话就可以算一次,否则算二,按长度排序,看重量,dfs暴力搞就可以,满足条件就继续找下一个比当前这个重量大的,记得找到就break,

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

typedef struct node
{
    int hight;
    int weight;
}stu;

int n,book[5010];;
stu a[5010];

int cmp(stu a,stu b)
{
    return (a.hight == b.hight) ? (a.weight < b.weight ) : (a.hight < b.hight);
}

void dfs(int i)
{
    for (int j = i+1 ; j < n ;j++)
    {
        if(!book[j] && a[j].weight >= a[i].weight)
        {
            book[j] = 1;
            dfs(j);
            break;
        }
    }
}

int main()
{
    int t;
    scanf("%d",&t);

    while (t--)
    {
        scanf("%d",&n);
        int ans = 0;

        for (int i = 0 ; i < n ;i++)
            scanf("%d%d",&a[i].hight,&a[i].weight);
        sort(a,a+n ,cmp);

        memset(book,0,n*sizeof(int));

        for (int i = 0 ; i < n ;i++)
            if(!book[i])
        {
            ans++;
            book[i] = 1;
            dfs(i);
        }

        printf("%d\n",ans);
    }
}

你可能感兴趣的:(小灶第四次作业:周赛补题)