1. 程式人生 > 其它 >NowCoder2018多校A Ternary String 拓展尤拉定理

NowCoder2018多校A Ternary String 拓展尤拉定理

NowCoder2018多校A Ternary String 拓展尤拉定理

題意

給定帶前導0的三進位制數,每秒自動進行一次操作,1的後面多一個0,2的後面多一個1,開頭的字元被刪除,求這個數變為空的操作次數

求操作次數取模\(1e9+7\)

\[1 \leq |s| \leq 10^5 \]

分析

考慮記錄時間,原串中每個數帶來的貢獻,可以簡單歸納得出

0:\(t + 1\)

1:\(2(t + 1)\)

2:\(3(2^{t + 1} - 1)\)

操作12都可以輕鬆得到結果,對於3,計算\(2^{t + 1} \ mod \ MOD\)是不方便的,考慮使用拓展尤拉定理

\[a^b \equiv \begin{cases} a^{b \bmod \varphi(m)},gcd(a,m) = 1\\ a^b ,gcd(a,m) \neq 1,b \leq \varphi(m) (mod \ m)\\ a^{b \ mod \varphi(m) +\varphi(m)},gcd(a,m) \neq 1,b \geq \varphi(m) \end{cases} \]

使用時,要求冪對\(\varphi(m)\)

取模,因此我們記錄\(t\)時還需額外記錄\(\varphi(m)\)意義下的\(t\),維護\(\varphi(m)\) 意義下的\(t\)又需要巢狀上模\(\varphi(\varphi(m))\)

為了方便實現,可以採用DFS的方式記錄當前第幾個數和當前的模數,至於為什麼不用判斷\(b \geq \varphi(m)\),我也不是很懂

程式碼

const int MOD = (int)1e9 + 7;

int m[35],ans[35];


inline int mul(int a,int b,int i){
    return (ll)a * b % i;
}


inline  void add(int &a,int b,int i){
    a += b;
    if(a >= i) a -= i;
}

inline int ksm(int a,ll b = MOD - 2,int m = MOD){
    int ans = 1;
    int base = a;
    while(b){
        if(b & 1) {
            ans = (ll)ans * base % m;
        }
        base = (ll)base * base % m;
        b >>= 1;
    }
    return ans;
}


inline int get_phi(int n) {
    int m = int(sqrt(n + 0.5));
    int ans = n;
    for (int i = 2; i <= m; i++) {
        if (n % i == 0) {
            ans = ans / i * (i - 1);
            while (n % i == 0) n /= i;
        }
    }
    if (n > 1) ans = ans / n * (n - 1);
    return ans;
}

unordered_map<int,int> mp;
char s[100005];

int dfs(int len,int m){
    if(!len) return 0;
    if(s[len] == '0')
        return (dfs(len - 1,m) + 1) % m;
    if(s[len] == '1') 
        return (ll)2 * (dfs(len - 1,m) + 1) % m;
    //if(mp[m] != 1) return (mul(3,ksm(2,(dfs(len - 1,mp[m]) + 1) % mp[m],m),m) + m - 3) % m;
    int p = dfs(len - 1,mp[m]) + 1;
    if(m != 1 && m != MOD) {
        if(p >= mp[m]) return (mul(3,ksm(2,p % mp[m] + mp[m],m),m) + m - 3) % m;
        else return (mul(3,ksm(2,p % mp[m],m),m) + m - 3) % m;
    }  
    return (mul(3,ksm(2,p % mp[m],m),m) + m - 3) % m;
}

int main(){
    int T = rd();
    int tmp = MOD;
    mp[1] = 1;
    while(tmp > 1) {
        mp[tmp] = get_phi(tmp);
        tmp = mp[tmp];
    }
    while(T--){
       scanf("%s",s + 1);
       int len = strlen(s + 1);
       printf("%d\n",dfs(len,MOD));
    }
}