来追梦-D1295 小F过河
<h1 id="前言">前言</h1><p>依旧是固定的前言。<br>
拿下了第四名,和第三名同分结果提交次数多了。<br>
发现第三名是我的同学并且比我弱之后大胆猜测他使用的奇怪的方法。<br>
结果看了他T3的代码,的确如此,他居然转移的时候只转移前面和后面的 <span class="math inline">\(500\)</span> 个,然后数据太水过了。<br>
显然是在模仿CCF,数据也太好了(确信。</p>
<p>话不多说,我的得分情况:90+100+20+0=210,第一题没有做出来挺离谱的,所以我写T2题解<br>
接下来开始我们的正题</p>
<h1 id="题目意思">题目意思</h1>
<p>你现在有两种操作,一种是将你现在手持的数字加上 <span class="math inline">\(x_1\)</span> 耗费 <span class="math inline">\(c_1\)</span> 的价值,另一种是将手持的乘上 <span class="math inline">\(x_2\)</span> 耗费 <span class="math inline">\(c_2\)</span> 的价值,要你从 <span class="math inline">\(1\)</span> 变到 <span class="math inline">\(N\)</span> 的最小价值,如果不行就报告不可能。</p>
<h1 id="题目思考">题目思考</h1>
<p>这是我在草稿纸上面的思路:<br>
首先我们可以将多次的加合并为 <span class="math inline">\(+ tx_1\)</span>,多次的乘合并为 <span class="math inline">\(\times x_2^t\)</span><br>
我尝试证明操作序列为 <span class="math inline">\(+ \times +\)</span> 或者 <span class="math inline">\(\times + \times\)</span>,但是发现不能证明,所以这说明他可能进行了若干次 <span class="math inline">\(+ \times\)</span> 的操作,所以不妨设我们依次进行了 <span class="math inline">\(n_1\)</span> 次 <span class="math inline">\(+\)</span> 操作,<span class="math inline">\(m_1\)</span> 次 <span class="math inline">\(\times\)</span> 操作,<span class="math inline">\(n_2\)</span> 次 <span class="math inline">\(+\)</span> 操作,<span class="math inline">\(m_2\)</span> 次 <span class="math inline">\(\times\)</span> 操作,以此类推。<br>
此时我们考虑他的最终数字,经过 <span class="math inline">\(n_1\)</span> 次 <span class="math inline">\(+\)</span> 操作后变为 <span class="math inline">\(1+n_1x_1\)</span>,经过 <span class="math inline">\(m_1\)</span> 次操作后变为 <span class="math inline">\((1+n_1x_1)x_2^{m_1}\)</span>,经过 <span class="math inline">\(n_2\)</span> 次 <span class="math inline">\(+\)</span> 操作,<span class="math inline">\(m_2\)</span> 次 <span class="math inline">\(\times\)</span> 后变为</p>
<p></p><div class="math display">\[((1+n_1x_1)x_2^{m_1}+n_2x_1)x_2^{m_2}
\]</div><p></p><p></p><div class="math display">\[=x_2^{m_1+m_2}+n_1x_1x_2^{m_1+m_2}+n_2x_1x_2^{m_2}
\]</div><p></p><p></p><div class="math display">\[=x_2^{m_1+m_2}+x_1(n_1x_2^{m_1+m_2}+n_2x_2^{m_2})
\]</div><p></p><p></p><div class="math display">\[=x_2^t+x_1(n_1x_2^{t-1}+n_2x_2^{t-2}+\cdots)
\]</div><p></p><p>接下来式子就化的差不多了,我们去看经过这些操作时候他的代价是多少,经过 <span class="math inline">\(n_1\)</span> 次 <span class="math inline">\(+\)</span> 操作,<span class="math inline">\(m_1\)</span> 次 <span class="math inline">\(\times\)</span> 操作后,代价是 <span class="math inline">\(n_1c_1+m_1c_2\)</span>,现在还看不出什么,但经过 <span class="math inline">\(n_2\)</span> 次 <span class="math inline">\(+\)</span> 操作,<span class="math inline">\(m_2\)</span> 次 <span class="math inline">\(\times\)</span> 后,代价变为 <span class="math inline">\(n_1c_1+m_1c_2+n_2c_1+m_2c_2=(n_1+n_2)c_1+(m_1+m_2)c_2\)</span> 然后观察 <span class="math inline">\(c_1\)</span> 前面的系数,发现 <span class="math inline">\((n_1+n_2)\)</span> 就是最后变成的数字里面,含有 <span class="math inline">\(x_1\)</span> 的项前面的系数!观察 <span class="math inline">\(c_2\)</span> 的系数,发现 <span class="math inline">\((m_1+m_2)\)</span> 就是最高次项的次数,也就是所谓的 <span class="math inline">\(t\)</span>,所以正确思路就出来了。</p>
<h1 id="思路">思路</h1>
<p>我们发现 <span class="math inline">\(x_2^{m_1+m_2}\le n\)</span> 所以我们枚举 <span class="math inline">\(m_1+m_2\)</span> 的值,除非 <span class="math inline">\(x_2=1\)</span> 这个值必然小于 <span class="math inline">\(64\)</span>,所以首先我们特判 <span class="math inline">\(x_2\)</span> 的值,接着我们对于每一个枚举的 <span class="math inline">\(m_1+m_2\)</span>,<span class="math inline">\(c_2\)</span> 的贡献已经固定了,所以我们要使 <span class="math inline">\(c_1\)</span> 的贡献尽量小,观看式子 <span class="math inline">\(x_1x_2^t>x_1x_2^{t-1}\)</span> 所以我们要让 <span class="math inline">\(x_1x_2^t\)</span> 的系数尽可能大,接着是 <span class="math inline">\(x_1x_2^{t-1}\)</span> 的系数尽可能大,这样就能让系数之和尽可能小了,具体的可以尝试借助代码理解,我就使用了 <span class="math inline">\(int128\)</span> 存储,不然可能炸掉。</p>
<h1 id="代码">代码</h1>
<pre><code class="language-cpp">#include<algorithm>
#include<iostream>
#include<cstring>
#include<climits>
#include<cmath>
#define ll __int128
using namespace std;
const ll Inf=0x3f3f3f3f3f3f3f3f,N=1e5+9;
ll n,x,xx,c,cc,a,ans;
int main(){
int garbage,T;
cin>>garbage>>T;
while(T--){
long long inputn,inputx,inputc,inputcc,inputxx;
cin>>inputn>>inputx>>inputc>>inputxx>>inputcc;
n=inputn;x=inputx;c=inputc;xx=inputxx;cc=inputcc;
if(xx<=1){
if(x==0){
cout<<"-1\n";
continue;
}
if((n-1)%x==0) cout<<(long long)(c*(n-1)/x)<<endl;
else cout<<"-1\n";
continue;
}
ll cnt=1;a=1;ans=Inf;
while(a<=n) a=a*xx,cnt++;
cnt--;
for(int i=cnt;i>=0;i--){
ll nn=n-a,nans=i*cc;
if(nn<0) continue;
for(int j=i;j>=0;j--){
if(a>(n+x-1)/x) continue;
if(nn>=x*a){
ll tmp=nn/(x*a);
nans+=tmp*c;
nn%=(x*a);
}
}
if(nn!=0) continue;
ans=min(ans,nans);
}
if(ans==Inf) cout<<"-1\n";
else cout<<(long long)ans<<endl;
}
return 0;
}
</code></pre>
<h1 id="后记">后记</h1>
<p>剩下的就是这个题目的思考了,写完了我仍然十分震撼我做出了这个题目,每一步仿佛都是机缘巧合,但是最后我还是死磕出来了,挺幸运的吧,如果下次没有这么幸运的话我还是希望我能通过我的努力把这种题目做出来,总结一下,以后遇到这种题目要愿意去推式子,求价值,不要怕就好了。</p><br><br>
来源:https://www.cnblogs.com/zhongyq-with-yuanqiu/p/19007855
頁:
[1]