题意
给你个板子板子上有一串数(一个字符串str+字符串重复的次数)让你去掉任意的数(不能全删)使之成为能够被5整除的数,问共有多少种方
法(%1000000007)m= 1000000007
PS 1) 允许有前导0
2) 板子上不同位置的数去掉是不同的答案 比如 115 去掉第一个1和去掉第二个1是两种方法
分析
1)可以被5整除的数:结尾为0或者5的数即可被5整除
2)删除的方法:当第I位数为5或者0时 那么一共有2^i种方法(i起始于0)
一个str(不算重复的)中共有 a{1} = 2^0*(str[0]==5||str[0]==0)+……+2^i*(str[i]==5||str[i]==0).......
所有str(算上重复的)构成等比数列
a{n}=a{1}*q^(n-1)
其中 q= 2^strlen(str).
和值: sum = (a{1} *(q^n-1 )/(q-1) )%m
分析结果
我们需要求的就是 sum = a{1} *(q^n-1 )/(q-1) %m 但是有两个重点问题需要解决
1)求指数运算比较大直接算会超时: 可以使用快速指数幂来进行求快速的求解
2)对于sum的球模 中间会有除法: 让我们想到求逆元使之变成乘法运算
3)转换为乘法:见下文中的费马定理求逆元之后
快速指数幂
网上有很多 讲的很好 直接百度过来
1)定义
快速幂顾名思义,就是快速算某个数的多少次幂。其时间复杂度为 O(log2N), 与朴素的O(N)相比效率有了极大的提高。以下以求a的b次方来介绍2)原理
把b转换成2进制数该2进制数第i位的权为(2^(i-1))例如a^11=a^(2^0+2^1+2^3)11的二进制是1 0 1 111 = 2^3*1 + 2^2*0 + 2^1*1 + 2^0*1因此,我们将a^11转化为算a^(2^0)*a^(2^1)*a^(2^3)3)代码比较
常规求幂
int pow1( int a, int b ) {int r = 1;while( b-- )r *= a;return r;}二分求幂(一般)
int pow2( int a, int b ) {int r = 1, base = a;while( b != 0 ) {if( b % 2 )r *= base;base *= base;b /= 2;}return r;}快速求幂(位操作)
int pow3( int a, int b ) {int r = 1, base = a;while( b != 0 ) {if( b & 1 )r *= base;base *= base;b >>= 1;}return r;}
费马定理求逆元
费马小定理是数论中的一个重要定理,其内容为: 假如p是质数,且gcd(a,p)=1,那么 a^(p-1) ≡1(mod p) 假如p是质数,且a,p互质,那么 a的(p-1)次方除以p的余数恒等于1
上面的分析结果
转换为乘法
我们要求
sum = a{1} *(q^n-1 )/(q-1) %m
sum = a{1}%m*( (q^n-1)/(q-1))%m
其中a{1}%m很好算
剩下的问题只是temp= ( (q^n-1)/(q-1))%m
为了方便起见 设 x=(q^n-1) y=(q-1) y的逆元为yy(别急一会儿求)
剩下的问题就变成了求 temp=(x/y)%m
已知逆元 y*yy%m==1(逆元的知识自己百度吧)
temp= (x/y)%m = (x/y)%m *(y*yy)%m = ((x/y)*(y*yy))%m = (x*yy)%m
已知 gcd(y,m)=1 且 m是质数
由小费马定理可以知道
y^(m-1)%m=( y*y^(m-2) )%m=1
因此 y的逆元 即yy =y^(m-2)
又因为 temp = (x*yy)%m
所以 temp = (x*y^(m-2))%m
所以SUM = (a{1}*(x*y^(m-2)))%m
= (a{1}*( (q^n-1)* (q-1) ^(m-2)))%m
所以::::把sum用快速指数幂算一遍就行了··············
AC代码:
#include<iostream> #include<cstdio> #include<stdlib.h> #include<cstring> using namespace std; const long long M = 1000000007; long long pow3( long long a, long long b ) { long long r = 1, base = a; while( b != 0 ) { if( b & 1 ) r = (r*base)%M; base = ( base * base ) % M; b >>= 1; } return r; } int main() { char s[300000]; long long n; while(gets(s)) { cin>>n; getchar(); long long sLen = strlen(s); long long sum = 0; long long base = 1; for(int i=0;i<sLen;i++) { if( s[i]=='0' || s[i] == '5' ) { sum = ( sum + base )%M; } base = (base * 2)%M; } long long q = pow3(2,sLen); long long a1 = sum; int top = (pow3(q,n)+M-1)%M; int buttom = pow3((q+M-1)%M,M-2)%M; sum = (a1*top)%M; sum = (sum*buttom)%M; cout<<sum<<endl; } }
相关推荐
用c语言实现逆元的计算,通过自己设计算法代码实现。
扩展欧几里得算法求逆元
数论
求解乘法逆元的方法之一就是使用扩展欧几里得算法。 扩展欧几里得算法是欧几里得算法的一种扩展,不仅能够找到两个整数的最大公约数(GCD),还能同时计算出它们的贝祖等式解。贝祖等式是这样的形式:ax + by = gcd...
在信息安全与保密领域,计算模数的逆元是加密算法中的关键步骤,特别是在涉及模运算的密码系统中,如RSA公钥加密系统。模逆元的求解是数学中的一个基本问题,它与数论紧密相关。本篇将详细介绍如何使用辗转相除法,...
用递归实现的求逆元的代码,使用中的算法是扩展的欧几里得算法。输入本元和模数,得到乘法逆元。
费马小定理是一种特殊情况下的逆元计算方法,当模数为素数时,a的逆元可以快速得到,即a^(c-2) mod c,其中c是素数。费马小定理的核心在于,当p为质数时,任何不为p的倍数的整数a的逆元就是a^(p-2) mod p。快速幂...
3. **求解逆元**:当余数为1时,根据扩展欧几里得算法的原理,可以求出满足\( a \cdot x + n \cdot y = 1 \)的\( x \)和\( y \),其中\( x \)即为所求的乘法逆元。 下面是一段C语言代码示例,用于计算\( a \)模\( n...
关于 线性求逆元 算法的代码,自己写的,和大家分享,希望大家能多多指教
a,b较小时 2000 #include using namespace std; const int N = 2010, mod = 1e9 + 7; int c[N][N]; int n; int main() ... c[x][y] <...a,b较大时 利用乘法逆元求 a,b为10^5 #include #include #inclu
欧几里得是数论中的一个最初步的概念,它用来判断两个数的最大公因子,扩展的欧几里得能够进一步实现在两个数互素情况下的乘法可逆元。求可逆元是一些算法的基础。
本文将详细介绍如何使用扩展欧几里得算法求解一个整数\( a \)在模\( f \)下的逆元,并提供一个基于VC++6.0的实现示例。 #### 扩展欧几里得算法原理 扩展欧几里得算法不仅能够求解两个整数的最大公约数(GCD),还...
群判定,逆元,元素的阶 #include using namespace std; #define N 10000 //对四元群运算函数的定义 char ysuan(char a,char b) { char arr[4]={'a','b','c','e'}; int i=0,j=0; if(a==b) { return arr[3]; }...
在这个场景下,我们关注的是如何使用扩展欧几里得算法来求解多项式的乘法逆元,特别是在MATLAB环境下实现这一算法。 在环\[ \mathbb{Z}[x] \]中,如果有一个多项式\( f(x) \),它的乘法逆元是指存在另一个多项式\( ...
根据提供的文件信息,本文将详细解释如何利用欧几里德算法在MATLAB环境中求解逆元问题,并通过示例代码加深理解。 ### 欧几里德算法与逆元概念 #### 欧几里德算法 欧几里德算法(Euclidean Algorithm),又称为...
### 乘法逆元与扩展欧几里得算法 #### 一、乘法逆元的基本概念 乘法逆元在密码学中具有重要的地位,它指的是对于一个整数 \( a \) 在模 \( p \) 意义下存在一个整数 \( b \),使得 \( ab \equiv 1 \pmod{p} \) ...
用C语言简单实现乘法逆元计算的代码(!只能计算正整数)
计算乘法逆元有多种方法,包括扩展欧几里得算法、费马小定理和中国剩余定理等。扩展欧几里得算法是最常用的,因为它能同时找到最大公约数和逆元,时间复杂度为O(log n)。 在给定的压缩包文件"求乘法逆元"中,可能...
在C语言中,我们可以使用扩展欧几里得算法来求解模逆元。 **扩展欧几里得算法**是求解最大公约数(GCD)的一个过程,同时也能得到模逆元。算法基于欧几里得定理:对于任何两个正整数a和b,存在整数x和y使得gcd(a, b...
这个“android多项式求乘法逆元小软件源码”提供了一个实用的解决方案,尤其对于需要处理数学问题的开发者来说,具有很高的价值。下面我们将详细探讨相关知识点。 1. **多项式**: 多项式是数学中的基本概念,由...