【luogu 2529】【SHOI 2001】击鼓传花

【原题题面】传送门

【题解大意】

这篇题解写得太清晰易懂了,我就不赘述了。

讲讲在上面那篇博客中没有直接写出来但是可能影响理解的东西:

f(x) = f(x/5) × a(x % 20)

已知非零的最后一位一定是偶数之后,我们考虑把每20个数分成一组,这样他们相乘4*4%10==6

对后面分不成一块的数的乘积(无论为多少,都毫不影响。

算法的实现:

我们给出的数记作x,起答案为ans[x]。

1.高精%单精(20) = y;

2.答案记作为ans[x] = a[y]*ans[x/5];

ans[x] = a[y]*ans[x/5] = a[y1]*a[y2]*ans[x/5/5] = ...

直到 x<20.

关于a数组的预处理应该为:

1,2,3,4,1/2,5,6,7,8,9,1/2,11,12,13,14,1/2,16,17,18,19,1/2的前缀乘并且时刻记住%10。

每20个数分组,所以分不到组内的数的个数小于20.即我们需要预处理的数的个数小于20。

【code】

#include<bits/stdc++.h>
using namespace std;
#define File ""
#define ll long long
inline void file(){
    freopen(File".in","r",stdin);
    freopen(File".out","w",stdout);
}
const int mxn = 110;
char s[mxn];
int T,a[mxn],b[22],n;

inline int calc1(){
    return (a[2]*10+a[1]) % 20;
}

inline void calc2(){
    int t = 0;
    for(int i = n;i >= 1; --i){
        t = t*10+a[i];
        a[i] = t/5;
           t = t%5;
    }
}
int ans;
int main(){
//    file();
    T = 5,b[0] = 1;
    for(int i = 1;i <= 20; ++i){
        if(!(i%5)) b[i] = b[i-1]/2%10;
        else b[i] = b[i-1]*i%10;
    }
//    for(int i = 1;i <= 20; ++i) printf("%d ",b[i]);
//    puts("");
    while(T--){
        scanf("%s",s+1);
        n = strlen(s+1);
        for(int i = 1;i <= n; ++i) a[n-i+1] = s[i]-'0';
        ans = 1;
        while(n > 0){
            while(a[n]==0) n--;
            ans = ans*b[calc1()]%10;
            calc2();
        }
        printf("%d\n",ans);
    }
    return 0;
}
/*
11
12
13
14
15
*/
View Code

 

转载于:https://www.cnblogs.com/ve-2021/p/11076619.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值