每日一练 19.2.15

30 篇文章 0 订阅
18 篇文章 0 订阅

NOIP 2011 提高组

计算系数

题目描述
给定一个多项式(by+ax)k,请求出多项式展开后xn * ym 项的系数。

输入
共一行,包含5 个整数,分别为 a ,b ,k ,n ,m,每两个整数之间用一个空格隔开。0≤k≤1000, 0≤n,m≤k 且 n+m=k, 0≤a,b≤100,000

输出
输出共1 行,包含一个整数,表示所求的系数,这个系数可能很大,输出对10007 取模后的结果。

样例输入
1 1 3 1 2

样例输出
3

思路
通过公式
在这里插入图片描述
借用杨辉三角,即可推出答案

代码实现

#include <iostream>
#include <cstdio>
#include <string>
#include <queue>
#include <cstring>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <map>
#include <stack>

using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
const int mod=10007;
const int N=10005;
ll s[N][N];
ll qpow(ll k,ll n)
{
    ll ans=1;
    while(n>0)
    {
        if(n%2!=0) ans=ans*k%mod;
        k=k*k%mod;
        n/=2;
    }
    return ans;
}
int main()
{
    int a,b,k,n,m;
    scanf("%d%d%d%d%d",&a,&b,&k,&n,&m);
    s[1][1]=1;
    for(int i=2;i<=k+1;i++)
    {
        for(int j=1;j<=i;j++) s[i][j]=s[i-1][j-1]%mod+s[i-1][j]%mod;
    }
    cout<<s[k+1][k-n+1]*qpow(a,n)*qpow(b,m)%mod<<endl;
    return 0;
}

选择客栈

题目描述
丽江河边有 n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号。每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费。

两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中。晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 p。
他们想知道总共有多少种选择住宿的方案,保证晚上可以找到一家最低消费不超过 p元的咖啡店小聚。

输入
输入共n+1行。
第一行三个整数 n,k,p,每两个整数之间用一个空格隔开,分别表示客栈的个数,色调的数目和能接受的最低消费的最高值;
接下来的 n行,第 i+1 行两个整数,之间用一个空格隔开,分别表示 i 号客栈的装饰色调和 i 号客栈的咖啡店的最低消费。

2 ≤n ≤200,000,0<k ≤50,0≤p ≤100 , 0 ≤最低消费≤100。

输出
输出只有一行,一个整数,表示可选的住宿方案的总数。

样例输入
5 2 3
0 5
1 3
0 2
1 4
1 5

样例输出
3

提示
输入输出样例说明:

客栈编号 1 2 3 4 5

色调 0 1 0 1 1

最低消费 5 3 2 4 5

2 人要住同样色调的客栈,所有可选的住宿方案包括:住客栈①③,②④,②⑤,④⑤,

但是若选择住 4、5 号客栈的话,4、5 号客栈之间的咖啡店的最低消费是 4,而两人能承受

的最低消费是 3 元,所以不满足要求。因此只有前 3 种方案可选。

思路:
从右向左看,如果其左边又符合条件的咖啡店,并且存在相同颜色的客栈,则方案数加一,那么如果以这个右边的旅店作为对应点,将所有在左边而且颜色与之相
同的旅店数相加,就能得出很多种住宿方法了。那么用这个办法,用所有的对应点对应过去,就能最快的时间内找出所用的酒店了。

代码实现

#include <iostream>
#include <cstdio>
#include <string>
#include <queue>
#include <cstring>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <map>
#include <stack>

using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
const int mod=10007;
const int N=2000005;
int t[N],last[N],num[N];
int ans,now;
int main()
{
    int n,k,p;
    scanf("%d%d%d",&n,&k,&p);
    for(int i=0;i<n;i++)
    {
        int co,mo;
        scanf("%d%d",&co,&mo);
        if(mo<=p) now=i; //在次数为i时,在now限度下是否有可用咖啡店
        if(now>=last[co]) t[co]=num[co];//若在可用咖啡店,则左边的所有颜色相同的客栈都可用
        num[co]++;//颜色为co的客栈数+1
        ans+=t[co];
        last[co]=i;//记录最后一次遇见颜色为co的客栈的位置
    }
    printf("%d\n",ans);
    return 0;
}

NOIP 2012 普及组

寻宝

题目描述
传说很遥远的藏宝楼顶层藏着诱人的宝藏。小明历尽千辛万苦终于找到传说中的这个藏宝楼,藏宝楼的门口竖着一个木板,上面写有几个大字:寻宝说明书。说明书的内容如下:

藏宝楼共有N+1层,最上面一层是顶层,顶层有一个房间里面藏着宝藏。除了顶层外,藏宝楼另有N层,每层M个房间,这M个房间围成一圈并按逆时针方 向依次编号为0,…,M-1。其中一些房间有通往上一层的楼梯,每层楼的楼梯设计可能不同。每个房间里有一个指示牌,指示牌上有一个数字x,表示从这个房 间开始按逆时针方向选择第x个有楼梯的房间(假定该房间的编号为k),从该房间上楼,上楼后到达上一层的k号房间。比如当前房间的指示牌上写着2,则按逆 时针方向开始尝试,找到第2个有楼梯的房间,从该房间上楼。如果当前房间本身就有楼梯通向上层,该房间作为第一个有楼梯的房间。

寻宝说明书的最后用红色大号字体写着:“寻宝须知:帮助你找到每层上楼房间的指示牌上的数字(即每层第一个进入的房间内指示牌上的数字)总和为打开宝箱的密钥”。

请帮助小明算出这个打开宝箱的密钥。

输入
第一行2个整数N和M,之间用一个空格隔开。N表示除了顶层外藏宝楼共N层楼,M表示除顶层外每层楼有M个房间。
接下来N*M行,每行两个整数,之间用一个空格隔开,每行描述一个房间内的情况,其中第(i-1)*M+j行表示第i层j-1号房间的情况 (i=1,2,…, N;j=1,2,…,M)。第一个整数表示该房间是否有楼梯通往上一层(0表示没有,1表示有),第二个整数表示指示牌上的数字。注意,从j号房间的楼梯 爬到上一层到达的房间一定也是j号房间。
最后一行,一个整数,表示小明从藏宝楼底层的几号房间进入开始寻宝(注:房间编号从0开始)。

0<N≤10000,0<M≤100,0<x≤1,000,000

输出
输出只有一行,一个整数,表示打开宝箱的密钥,这个数可能会很大,请输出对20123取模的结果即可。

样例输入
2 3
1 2
0 3
1 4
0 1
1 5
1 2
1

样例输出
5

思路:
模拟小明上楼的过程,在输入数据是记录每一层有楼梯房间的个数,以提高效率

代码实现

#include <iostream>
#include <cstdio>
#include <string>
#include <queue>
#include <cstring>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <map>
#include <stack>

using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
const int mod=20123;
const int N=10005;
bool lt[N][105];
int c[N],ro[N][105];
int ans;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<m;j++)
        {
            int temp;
            scanf("%d%d",&temp,&ro[i][j]);
            if(temp)
            {
                c[i]++;
                lt[i][j]=true;
            }
        }
    }
    int now;
    scanf("%d",&now);
    for(int i=1;i<=n;i++)
    {
        ans+=ro[i][now];
        ans%=mod;
        if(i==n) break;
        int temp=ro[i][now]%c[i];
        if(!temp) temp=c[i];
        for(int j=1;j<=temp;j++)
        {
            while(!lt[i][now])
            {
                now++;
                now%=m;
            }
            if(j==temp) break;
            now++;
            now%=m;
        }
    }
    printf("%d\n",ans%mod);
    return 0;
}

摆花

题目描述
小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆。通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号。为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时同一种花放在一起,且不同种类的花需按标号的从小到大的顺序依次摆列。

试编程计算,一共有多少种不同的摆花方案。

输入
第一行包含两个正整数n和m,中间用一个空格隔开。
第二行有n个整数,每两个整数之间用一个空格隔开,依次表示a1、a2、……an。

0<n≤100,0<m≤100,0≤ ai≤100

输出
输出只有一行,一个整数,表示有多少种方案。注意:因为方案数可能很多,请输出方案数对1000007取模的结果。

样例输入
2 4
3 2

样例输出
2

思路:
用DP的方法,由题可得状态转移方程

dp[i][j]=dp[i-1][j]+dp[i-1][j-1]……+dp[i-1][j-a[i]]

代码实现

#include <iostream>
#include <cstdio>
#include <string>
#include <queue>
#include <cstring>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <map>
#include <stack>

using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
const int mod=1000007;
const int N=105;
int a[N];
int dp[N][N];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    dp[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int k=0;k<=m;k++)
        {
            for(int j=0;j<=a[i] && j<=k;j++)
            {
                dp[i][k]+=dp[i-1][k-j];
                dp[i][k]%=mod;
            }
        }
    }
    printf("%d\n",dp[n][m]);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值