第四周组队赛130804

F. Final Exam Arrangement

题意:有一些考试,给出起始时间和结束时间,若两场考试有重合,则可以安排在同一天,问最少要安排几天以及输出方案

其实这题不难,当时ran写了,但是WA了,今天我自己写了一下一交Wa了!我一直弄不明白为什么WA,后面我发现其实我考虑错了,我之前是对时间从小到大排序,开始时间相同的按结束世间从大到小排序,我选了第一个作为标准,以后从2-n里找有与1重合的就为一天,那时错的!!!因为所谓重合应该是这些被我安排成一天的考试,他们之间都有重和点,而不是与第一个考试有重合点就行,这样吧,为了更加强记忆,我画一下。。

1. |___________|  

2. |___________|

3.     |_____________|

4.          |___|

5.                     |_________|

我错就错在其实5和1有交点,但是和4没交点,我还是把它归为和1 2 3 4 一天了!!说多都是泪,以后多理解题目。。。

为了调整防止出现5和4没交点的情况,不时调整右端点

代码:

#include <stdio.h>//F
#include <iostream>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
struct node
{
    int l,r;
    int num;
} a[100005];
vector<int>v[100005];
bool cmp(node a,node b)
{
    if(a.l==b.l)
        return a.r<b.r;
    return a.l<b.l;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<=n;i++)
        v[i].clear();
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d",&a[i].l,&a[i].r);
            a[i].num=i;
        }
        sort(a+1,a+n+1,cmp);
        int day=1;
        int g=1;
        v[day].push_back(a[1].num);
        for(int i=2; i<=n; i++)//WA 的原因是少考虑了当L不相同时,R有可能比标准小,所以要更新r的情况
        {
            if(a[i].l>=a[g].l && a[i].l <a[g].r)
            {
                v[day].push_back(a[i].num);
                if(a[g].r>a[i].r)
                g=i;
            }
            else
            {
                day++;
                v[day].push_back(a[i].num);
                g=i;
            }
        }
        printf("%d\n",day);
        for(int i=1; i<=day; i++)
        {
            printf("%d",v[i][0]);
            for(int j=1; j<v[i].size(); j++)
            {
                printf(" %d",v[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

J. Painting Storages

题意:有n 个珠子,有红色和蓝色两种颜色,求至少有m个连续的红色珠子的方案数。。

我一拿到题目就看这题了,知道跟dp差不多,要推,当时我想简单了,后来宝神提供了他的想法,顺着他的想法,我一直在琢磨,最后推出了完整的公式,很兴奋的套上公式,一交WA了!唉~不用说了,long long 就过了

思路:就拿m=2来推吧dp[i][2]代表n个珠子至少有2个连续的红色珠子的方案数,容易得出dp[2][2]=1;讨论i>=3的情况

1  2   3           红色代表之前已经算过了,再增添第三个珠子,可以有dp[3][2]=dp[2][2]*2+2^(3-2-1)-dp[3-2-1][2]

还是拿5个数来讲吧

1  2   3   4   5  假设已经算出了四个的情况,加上第五个,dp[5][2]=dp[4][2]*2+2^(5-2-1)-dp[5-2-1][2],蓝色部分是因为当4和5都是红色时,3位置必须是蓝色的,不然就重复计算了,所以剩下5-2-1=2个数,在这2个数里不能出现2个连续的珠子,不然也重复计算了(之前*2),所以要用组合知识去重,用总的排列数减去可以至少出现2个连续的珠子,所以公式2^(5-2-1)-dp[5-2-1][2]      就是这么来的   

总的:dp[n][m]=dp[n-1][m]*2+2^(n-m-1)-dp[n-m-1][m]   

可以看出m 固定了之后,只需要对dp[n]求就行了,直接dp[n]代表dp[n][m]

代码;

#include<iostream>//J
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int Mod = 1000000007;
long long dp[100005];
long long pw[100005];
int main()
{
    int m,n;
    pw[0]=1;
    for(int i=1;i<=100000;i++)
    {
        pw[i]=(pw[i-1]*2)%1000000007;
    }
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(dp,0,sizeof(dp));
        dp[m]=1;
        for(long long int i=m+1;i<=n;i++)
        {
            dp[i]=(dp[i-1]*2+pw[i-m-1]-dp[i-m-1])%1000000007;
        }
        cout<<(dp[n]+1000000007)%1000000007<<endl;
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值