牛客网暑期ACM多校训练营(第四场)A 题解 (欧拉降幂)

题意:给你一个长度小于1e5的串,每次进行一次操作,在字符1后面插入一个0.在字符2后面插入一个1,然后删除首字符。

然后问你需要操作多少次,字符串会变成空串。

先写个暴力程序找找规律。
下面给出我的暴力代码。

#include 
using namespace std;
string ch(string s)
{
    int n=s.size();
    string ans;
    for(int i=0;i<n;i++)
    {
        if(i!=0) ans+=s[i];
        if(s[i]=='1')
        {
            ans+='0';
        }
        else if(s[i]=='2')
        {
            ans+='1';
        }    
    }
    return ans;
}
int main()
{
    string s;
    while(cin>>s)
    {
            int ans=0;
        while(1)
        {
            if(s.size()==0) break;
            //cout<<s<<endl;
            s=ch(s);
            ans++;
        }
        cout<<ans<<endl;
    }
    return 0;
}

每次我们加个1,假设没加1之前的操作次数是x,那么加了1之后操作次数就是2x+2。

每次我们加个2,假设没加2之前的操作次数是x,那么加了2之后的操作次数就变成3*(2^(x+1)-1),这个怎么找到的呢。

我们看到类似9,21,45,93这种都是3的倍数,我们把他们都除以3,得到3,7,15,31...发现他们都是2^n-1,那么规律就找到了。

当我们每次加个0,操作次数就加1,这个没啥说的。

到这时我们递推一下就行了。
1: x+x+2
2: 3*2^(x+1)
0: x+1
然后我们交上去发现超时了%50!!难道评测姬坏掉了QAQ
没超时的大佬下面的不用看了~~~
仔细观察发现如果每次碰到2直接用快速幂算2^(x+1),那么n有2e6。极端情况下碰到全为2的串。我们每次都要算一次快速幂。那么评测姬
图片说明
就会类似于这样,咳咳!!然而我们必须每次都算一次快速幂。
那么如何优化类似于(a^b^c^d^e.....)%mod这种式子。需要用到一个叫欧拉降幂的知识 (先%一下欧拉orz)。
关于欧拉降幂我也是刚学的,然后学的东西写这篇博客里了
https://blog.csdn.net/qq_37632935/article/details/81264965
那么学会欧拉降幂后这题就可以预处理出(ph...(ph(ph(1e9+7)))的所有欧拉函数值了。不能每次都求,要把它们先记下来,不然还是会T。
给出代码

#include 
using namespace std;
typedef long long ll;
map m;
ll PH(ll x)
{
    ll res=x,a=x;
    for(ll i=2;i*i<=x;i++)
    {
        if(a%i==0)
        {
            res=res/i*(i-1);
            while(a%i==0) a/=i;
        }
    }
    if(a>1) res=res/a*(a-1);
    return res;
}
ll quick_pow(ll a,ll b,ll mod)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}
char s[100005];
ll dfs(ll i,ll mod)
{      
    if(i==0) return 0;
    else if(s[i]=='0') return (dfs(i-1,mod)+1)%mod;
    else if(s[i]=='2') return ((3ll*quick_pow(2,dfs(i-1,m[mod])+1,mod)-3)%mod+mod)%mod;
    else return (2*dfs(i-1,mod)+2)%mod;
}
int main()
{
    ll mo=1e9+7;
    while(mo!=1)
    {
        m[mo]=PH(mo);
        mo=m[mo];
    }
    m[1]=1;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll mod=1e9+7;
        cin>>s+1;
        int n=strlen(s+1);
        printf("%lld\n",dfs(n,mod));
    }
    return 0;
}
/*
1  x+2
2  3*2^(x+1)-x
*/

贴一个循环的代码。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod[100005];
ll quick_pow(ll a, ll b, ll mo)
{
    ll res = 1;
    while(b)
    {
        if(b & 1)
            res = res * a % mo;
        b >>= 1;
        a = a * a % mo;
    }
    return res;
}
ll euler(ll n)   //??euler(n)
{
    ll res = n, a = n;
    for(ll i = 2; i * i <= a; i++)
    {
        if(a % i == 0)
        {
            res = res / i * (i - 1); //?????????????????
            while(a % i == 0) a /= i;
        }
    }
    if(a > 1) res = res / a * (a - 1);
    return res;
}
char s[100005];
int main()
{
    mod[0] = 1e9 + 7;
    for(int i = 1; i < 1e5 + 5; i++)
    {
        mod[i] = euler(mod[i - 1]);
//        printf("%d---%lld\n",i,mod[i]);
    }
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%s", s);
        int cnt = 0;
        for(int i = 0; s[i] != 0; i++)
        {
            if(s[i] == '2')
                cnt++;
        }
        ll ans = 0;
        for(int i = 0; s[i] != 0; i++)
        {
            if(s[i] == '0')
            {
                ans++;
                ans %= mod[cnt];
            }
            else if(s[i] == '1')
            {
                ans = (ans + ans + 2) % mod[cnt];
            }
            else
            {
                cnt--;
                if(ans<mod[cnt])        
                    ans = 3ll * (quick_pow(2ll, (ans + 1) % mod[cnt], mod[cnt]) - 1 + mod[cnt]) % mod[cnt];                
                else
                { 
                    ans = 3ll * (quick_pow(2ll, (ans + 1) % mod[cnt]+mod[cnt], mod[cnt]) - 1 + mod[cnt]) % mod[cnt];
                }
            }

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

    }
}
全部评论
求问这个地方的欧拉降幂a^b%p  为甚麽默认b小于等于m[p]..直接采用a^(b%m[p]) %p 而不是  a^(b%m[p]+m[p])%p??? 即quick_pow(2,dfs(i-1,m[mod])+1,mod)为甚麽不是quick_pow(2,dfs(i-1,m[mod])+1+m[mod],mod)??
点赞 回复
分享
发布于 2018-07-28 22:37

相关推荐

8 收藏 评论
分享
牛客网
牛客企业服务