题解 P2558 【[AHOI2002]网络传输】
这道题其实可以找规律用动态规划来做哒!
我们以样例为基础,看看规律吧!
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3^0 | 3^1 | 3^0+3^1 | 3^2 | 3^0+3^2 | 3^1+3^2 | 3^0+3^1+3^2 | 3^3 | 3^0+3^3 | 3^1+3^3 | 3^0+3^1+3^3 | 3^2+3^3 | 3^0+3^2+3^3 | 3^1+3^2+3^3 | 3^0+3^1+3^2+3^3 | 3^4 |
相信一定有冰雪聪明的孩纸发现了规律,我们再用已知编号(<=当前编号)填一个表,我相信你一定会发现其中的奥妙滴!
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2 | 1+2 | 4 | 1+4 | 2+4 | 3+4 | 8 | 1+8 | 2+8 | 3+8 | 4+8 | 5+8 | 6+8 | 7+8 | 16 |
发现规律了吧!
单个编号(无+)的都是2^n次方,然后就又开始了一个新轮回。
我们设当前编号为i(2^n<i<2^n+1),当前的数为a[i]。
那么a[i]=a[n]+a[i%n] (或a[i]=a[n]+a[i-n] )
找到规律就很好办了,接下来就是各位孩纸们最爱的---代码上场了!!
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int k,p;
long long a[10000]={0};
long long pow(int a,int b)//快速幂(毕竟是算幂)
{
long long re=1,base=a;
while(b)
{
if(b&1)re=re*base;
base=base*base;
b>>=1;
}
return re;
}
int log2(int x)//高中孩纸都知道的(log2x=i就是 2^i=x)
{
int i,s=1;
for(i=1;i<=x;i++)
{
s=s*2;
if(s==x)break;
}
return i;
}
int main()
{
int n=0,i,c;
scanf("%d%d",&k,&p);
a[1]=1;//初始化
for(i=2;i<=p;i=i*2)//预处理,把每个单独的编号(2^i)算出来
{
c=log2(i);
a[i]=pow(k,c);
}
for(i=2;i<=p;i++)
{
if(a[i]!=0)//如果不为0,一定开始了一个新轮回
{
n=i;
continue;
}
a[i]=a[i%n]+a[n];//动态规划方程式搬出来
}
printf("%lld",a[p]);
return 0;
}
当然,看这数据规模一定是要用高精度的滴!
所以劳烦各位打个高精度。
然后便可以看见一片绿色,再加一朵大红花。
蒟蒻第一次写题解···
若有不懂或有问题,尽情指正,蒟蒻愿洗耳恭听 大佬们的指正。