牛客多校 Ternary String (数论)

2024-02-18 05:38

本文主要是介绍牛客多校 Ternary String (数论),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

A ternary string is a sequence of digits, where each digit is either 0, 1, or 2. Chiaki has a ternary string s which can self-reproduce. Every second, a digit 0 is inserted after every 1 in the string, and then a digit 1 is inserted after every 2 in the string, and finally the first character will disappear. For example, ``212'' will become ``11021'' after one second, and become ``01002110'' after another second. Chiaki would like to know the number of seconds needed until the string become an empty string. As the answer could be very large, she only needs the answer modulo (109 + 7).
输入描述:
There are multiple test cases. The first line of input is an integer T indicates the number of test cases. For each test case:The first line contains a ternary string s (1 ≤ |s| ≤ 105).It is guaranteed that the sum of all |s| does not exceed 2 x 106.
输出描述:
For each test case, output an integer denoting the answer. If the string never becomes empty, output -1 instead.

示例1

输入
复制

3
000
012
22

输出
复制

3
93
45

思路:

1. 如果遇到了 0, t++

2. 如果遇到了1,t = t*2+2

因为之前经历了t,那么就会派生出来t个0,加上一个1的时间 2 就是上式了

3. 如果遇到了2,t = 3*(2^t -1) 

可以类似于2来想,经过了t后到了一个2

会变成这样 21101001000100001.......

再过一秒会变成1101001000100001000001.......   // **** 等了一秒

观察这个序列可以发现:该序列满足2的结论 。

消灭到第一个1和他后面的0  需要  a1 = 2

消灭到第二个1和他后面的0  需要  a2 = 2*a1+2 + 2-1 = 7 

消灭到第三个1和他后面的0  需要  a3 = 2*a2+2 + 3-1 = 18

消灭到第 i 个1和他后面的0  需要  a[i] = 2*a[i-1]+2+i-1 = 2*a[i-1]+i+1

有了 a[i+1] = 2*a[i]+i+2,a[1] = 2, 就可以求a[n] 了

两边同时加 i+4 得到  a[i+1]+(i+1)+3 = 2(a[i]+i+3)

令b[n] = a[n]+n+3 , b1 = a1+4 = 6;

b[n+1]/b[n] = 2;  

得到 b[n] = 6*2^(n-1) = 3*2^n

得到 a[n] = b[n]-n-3 = 3*2^n-n-3

a[n] 就是在之前时间为n-1 (因为之前等了一秒)时,当前2消掉的花费了。

再加上之前的花费n-1 + 1可以算出总的当前花费 3*2^n-3

那么由于每次都要对前面的结果取一次指数,就得用指数循环节了

1e9+7 开始打个表,20多次phi就能打到1了·剩下的就是维护指数,和结果了

倒存一下mod,正向一遍出结果。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <stack>
#include <map>
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
char s[maxn];
stack <ll> mod;
ll qm(ll a, ll n, ll m)
{if(a >= m) a = a%m+m;ll ans = 1;while(n){if(n%2) {ans = ans*a;if(ans >= m) ans = ans%m+m;	}	a = a*a;if(a >= m) a= a%m+m;n/=2;}return ans;
}
map <int,ll> phi;
ll get_phi(ll n)
{ll ans = n;for(ll i = 2; i*i <= n; i++){if(n%i == 0) ans = ans-ans/i;while(n%i==0) n/=i;}if(n!=1) ans = ans-ans/n;return ans;
}int main()
{ll kk;phi[1] = 1;for(ll i = 1e9+7; i > 1; i=kk){kk = get_phi(i);phi[i] = kk;}int t;scanf("%d",&t);while(t--){scanf("%s",s);int len = strlen(s);while(mod.size()) mod.pop();ll md = 1e9+7;for(int i = len-1; i >= 0; i--){if(s[i] == '2') {mod.push(md);md = phi[md];}}ll ans = 0;ll tmp = 0;ll MOD = 1e9+7;if(mod.empty()) mod.push(MOD);for(int i = 0; s[i]; i++){if(s[i] == '0'){ans=(ans+1)%MOD;tmp=(tmp+1);if(tmp >= md) tmp = tmp%md+md;}if(s[i] == '1'){ans=(2LL*ans+2LL)%MOD;tmp=(2LL*tmp+2LL);if(tmp >= md) tmp = tmp%md+md;}if(s[i] == '2') {md = mod.top();mod.pop();tmp = 3LL*qm(2,tmp+1,md);ans = (tmp-3+MOD)%MOD;tmp = (tmp-3+md*MOD);if(tmp >= md) tmp = tmp%md+md;}}printf("%lld\n",ans);}return 0;
}

 

这篇关于牛客多校 Ternary String (数论)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/720203

相关文章

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

数论ZOJ 2562

题意:给定一个数N,求小于等于N的所有数当中,约数最多的一个数,如果存在多个这样的数,输出其中最大的一个。 分析:反素数定义:对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数。 性质一:一个反素数的质因子必然是从2开始连续的质数。 性质二:p=2^t1*3^t2*5^t3*7

POJ2247数论

p = 2^a*3^b*5^c*7^d 求形如上式的第n小的数。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.u

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

string字符会调用new分配堆内存吗

gcc的string默认大小是32个字节,字符串小于等于15直接保存在栈上,超过之后才会使用new分配。

CSP-J基础之数学基础 初等数论 一篇搞懂(一)

文章目录 前言声明初等数论是什么初等数论历史1. **古代时期**2. **中世纪时期**3. **文艺复兴与近代**4. **现代时期** 整数的整除性约数什么样的整数除什么样的整数才能得到整数?条件:举例说明:一般化: 判断两个数能否被整除 因数与倍数质数与复合数使用开根号法判定质数哥德巴赫猜想最大公因数与辗转相除法计算最大公因数的常用方法:举几个例子:例子 1: 计算 12 和 18

CSP-J基础之数学基础 初等数论 一篇搞懂(二)

文章目录 前言算术基本定理简介什么是质数?举个简单例子:重要的结论:算术基本定理公式解释:举例: 算术基本定理的求法如何找出质因数:举个简单的例子: 重要的步骤:C++实现 同余举个例子:同余的性质简介1. 同余的自反性2. 同余的对称性3. 同余的传递性4. 同余的加法性质5. 同余的乘法性质 推论 总结 前言 在计算机科学和数学中,初等数论是一个重要的基础领域,涉及到整数

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

牛客小白月赛100(A,B,C,D,E,F三元环计数)

比赛链接 官方讲解 这场比较简单,ABC都很签到,D是个不太裸需要预处理的 B F S BFS BFS 搜索,E是调和级数暴力枚举,F是三元环计数。三元环考的比较少,没见过可能会偏难。 A ACM中的A题 思路: 就是枚举每个边变成原来的两倍,然后看看两短边之和是否大于第三边即可。 不能只给最短边乘 2 2 2,比如 1 4 8 这组数据,也不能只给第二短边乘 2 2 2,比

hdu2072(string的应用)

单词数 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 25447    Accepted Submission(s): 5957 Problem Description lily的好朋友xiaoou333最近很空,他