ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AtCoder Beginner Contest 182 F

2021-09-08 13:01:59  阅读:203  来源: 互联网

标签:AtCoder ch Beginner bi 182 xi kx dp define


F - Valid payments

简化题意:有\(n\)种面值的货币,保证\(a[1]=1,且a[i+1]是a[i]的倍数\)。
有一个价格为\(x\)元的商品,付款\(y\)元,找零\(y-x\)元。
问满足以下条件的情况下的应支付金额\(y\)有多少种?
条件一:付款和找零都使用最少的硬币数量。
条件二:在满足条件一的情况下,付款是用过的硬币面值,找零时无法使用。
考虑这个题对于条件一而言,可以归结为第\(i\)个硬币食用的个数不能超过\(a[i+1]/a[i]\),否则的话我们直接使用\(a[i+1]\)会更优。这样的话在条件一的情况下,每个金额\(x\)都有唯一的表示方法:\(x=k_{x1}*a_1+k_{x2}*a_2+k_{x3}*a_3+...+k_{xn}*a_n\),这样的话我们令\(b=y-x\),则对于条件二而言限制条件就变成了\(k_{yi}和k_{bi}\)不能同时非零,即不能同时使用。
这样的话我们可以列出以下等式:
\(x=k_{x1}*a_1+k_{x2}*a_2+...+k_{xn}*a_n\)
\(+b=k_{b1}*a_1+k_{b2}*a_2+...+k_{bn}*a_n\)
\(y=k_{y1}*a_1+k_{y2}*a_2+...+k_{yn}*a_n\)
限制条件如下:\(k_i不能超过a[i+1]/a[i]\),且\(k_{yi}\)和\(k_{bi}\)不能同时非零。问不同的\(y\),或\(b\)的方案数?(可以发现\(y\)和\(b\)是一一对应的。)
由于\(k_{yi}\)和\(k_{bi}\)不能同时非零,则至少一个为\(0\),所以我们直接分类讨论就行:
1.若\(k_{yi}\)为0,则说明我们这里\(k_{xi}\)和\(k_{bi}\)相加的和必须也为0,但这怎么可能呢?考虑会不会是进位的问题呢?什么意思就是我的\(k_{xi}\)和\(k_{bi}\)都不超过\(a[i+1]/a[i]\)但我的和却超过它了,这样的话就可以用前面的替代了。那么这样的话也就是必须满足\(k_{xi}+k_{bi}+上一位的进位=a[i+1]/a[i]\).这样的话才能满足当前位为\(0\).
2.若\(k_{bi}\)为0,说明\(x_{ki}+上一位的进位=y_{ki}\)。
也就是说只要我们知道上一位是否进位,我们就可以根据当前\(x_{ki}\)来确定当前不同情况下的y和b了。具体的就是我们设\(dp[i][0/1]\)表示前\(i\)位,并且第\(i\)位进位/不进位的方案数。
则根据情况二有:\(dp[i][0]+=dp[i-1][0],dp[i][0]+=dp[i-1][1](k_{xi}!=a[i+1]/a[i]-1)\)
根据情况一有:\(dp[i][1]+=dp[i-1][1],dp[i][1]+=dp[i-1][0](k_{xi}!=0)\)。
由于金额最大的没有限定的使用数量,但我们发现\(k_{bn}\)只能为0.

//不等,不问,不犹豫,不回头.
#include<bits/stdc++.h>
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair<ll,int>
#define PII pair<int,int>
#define ull unsigned long long
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(x,y,z) for(int x=y;x<=z;++x)
#define fep(x,y,z) for(int x=y;x>=z;--x)
#define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=110;
ll n,x,a[N],mx[N],kx[N],dp[N][2];

inline ll read()
{
    ll x=0,ff=1;
    char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*ff;
}

int main()
{
    //freopen("1.in","r",stdin);
	get(n);get(x);
	rep(i,1,n) get(a[i]);
	rep(i,1,n-1) mx[i]=a[i+1]/a[i];
	fep(i,n,1)
	{
		if(x>=a[i])
		{
			kx[i]=x/a[i];
			x-=kx[i]*a[i];
		}
	}
	dp[0][0]=1;
	rep(i,1,n)
	{
		dp[i][0]+=dp[i-1][0];
		dp[i][1]+=dp[i-1][1];
		if(kx[i]!=mx[i]-1) dp[i][0]+=dp[i-1][1];
		if(kx[i]!=0) dp[i][1]+=dp[i-1][0];
	}
	putl(dp[n][0]);
    return (0^_^0);
}
//以吾之血,铸吾最后的亡魂.

标签:AtCoder,ch,Beginner,bi,182,xi,kx,dp,define
来源: https://www.cnblogs.com/gcfer/p/15242261.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有