Beautiful Trees Cutting (求逆元)

链接: https://www.nowcoder.com/acm/contest/106/B
来源:牛客网

题目描述


It’s universally acknowledged that there’re innumerable trees in the campus of HUST.


One day Xiao Ming is walking on a straight road and sees many trees line up in the right side. Heights of each tree which is denoted by a non-negative integer from 0 to 9 can form a tree string. It's very surprising to find that the tree string can be represent as an initial string repeating K times. Now he wants to remove some trees to make the rest of the tree string looks beautiful. A string is beautiful if and only if the integer it represents is divisible by five. Now he wonders how many ways there are that he could make it.

Note that when we transfer the string to a integer, we ignore the leading zeros. For example, the string “00055” will be seen as 55. And also pay attention that two ways are considered different if the removed trees are different. The result can be very large, so printing the answer (mod 1000000007) is enough. And additionally, Xiao Ming can't cut down all trees.

输入描述:

 
 
The first line contains a single integer K , which indicates that the tree string is the initial string repeating K times.
The second line is the initial string S .

输出描述:

A single integer, the number of ways to remove trees mod 1000000007.
示例1

输入

1
100

输出

6

说明

Initially, the sequence is ‘100’. There are
6 ways:
100
1_0
10_
_00
__0
_0_
示例2

输入

3
125390

输出

149796
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
 
const int mod=1e9+7;
const int maxn=1e5+10;
int val[maxn];
char str[maxn];
/*
等比数列
逆元 
*/
 
ll q_pow(ll base,int n){
    ll ans=1;
    while(n){
        if(n&1)
            ans=(ans*base)%mod;
        base=(base*base)%mod;
        n/=2;
    }
    return ans;
}
 

ll exgcd(ll a,ll b,ll &x,ll &y){
    if(a==0&&b==0) return -1;
    if(b==0){
        x=1,y=0;return a;
    }
    ll d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
 
ll NY(ll a,ll n){
    ll x,y;
    ll d=exgcd(a,n,x,y);
    if(d==1) return (x%n+n)%n;
    else return -1;
}

 
int main(){
    ll k;
    scanf("%lld",&k);
    scanf("%s",str);
    int len=strlen(str);
    for(int i=len-1;i>=0;i--){
        if(str[i]=='0'||str[i]=='5'){
            val[i]=i;
        }
    }
    ll ans=0;
    for(int i=0;i<len;i++){
        if(str[i]=='0'||str[i]=='5')
        ans=(ans+q_pow((ll)2,val[i]))%mod;
    }

    ll q=q_pow((ll)2,len);

    ll _q=NY(q-1,mod);
    ans=(ans*(q_pow(q,k)-1)%mod*_q%mod+mod)%mod;

 	printf("%lld\n",ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
欧几里得算法是一个用于计算两个整数的最大公约数的算法,扩展欧几里得算法可以在得最大公约数的同时计算出满足贝祖等式 ax + by = gcd(a,b) 的整数解 x 和 y,其中 a 和 b 是输入的整数。 扩展欧几里得算法可用于解模反元素(逆元),其中逆元是指某个整数关于模数的乘法逆元素。 下面是我用C语言实现扩展欧几里得算法逆元的示例代码: ``` #include <stdio.h> int extended_gcd(int a, int b, int *x, int *y) { if (b == 0) { *x = 1; *y = 0; return a; } int x1, y1; int gcd = extended_gcd(b, a % b, &x1, &y1); *x = y1; *y = x1 - a / b * y1; return gcd; } int mod_inverse(int a, int m) { int x, y; int gcd = extended_gcd(a, m, &x, &y); if (gcd != 1) { printf("逆元不存在\n"); return -1; // 逆元不存在 } int inverse = (x % m + m) % m; return inverse; } int main() { int a, m; printf("请输入要逆元的整数a和模数m:"); scanf("%d %d", &a, &m); int inverse = mod_inverse(a, m); if (inverse != -1) { printf("%d关于模数%d的逆元是:%d\n", a, m, inverse); } return 0; } ``` 这是一个简单的扩展欧几里得算法逆元的实现,首先通过`extended_gcd`函数出`a`和`m`的最大公约数,并计算满足贝祖等式的整数解`x`和`y`。如果最大公约数不为1,则逆元不存在。若最大公约数为1,则通过模的方式计算`x`关于模数`m`的逆元。代码中的`mod_inverse`函数用于调用`extended_gcd`函数,并处理逆元不存在的情况。最后,通过用户输入需要逆元的整数`a`和模数`m`,并输出结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值