Ссылка на тему: A-String J Группа лягушек квакать квакать квакать квакать
Строка
Тема
- Сколько строк состоит из строчных букв не более n и содержит подпоследовательность «us»? Ответ - по модулю 1e9 + 7.
- Последовательность, нас не может быть рядом
- Диапазон: 2≤n≤1e6
Идеи
- Математические формулы. Если вы хотите увидеть статус dp push, нажмите здесь ~
- Сложность обратная: найдите ту, которая не содержит подпоследовательности us, например, n равно 3.
- Выберите "нет" для всех трех, а затем всего 25 * 25 * 25
- Последний - s, затем u нельзя выбрать раньше, всего 25 * 25 * 1
- Второй выбирает s, затем предпоследний не может выбрать s, потому что он будет повторяться с 2, а первый не может быть u, всего 25 * 1 * 25
- Первый выбирает s, затем ни второй, ни последний не могут выбрать s, потому что он будет повторяться с предыдущим, всего 1 * 25 * 25
- Произвольно выберите 26 ^ 3, удалите 25 ^ 2 * 3 + 25 ^ 3, которые не содержат подпоследовательности us, затем оставшаяся часть содержит подпоследовательность us
- Таким образом, для строки длины n количество наших подпоследовательностей равно 26 ^ n-25 ^ (n-1) * n + 25 ^ n, и вычитание необходимо добавить по модулю, а затем по модулю.
код переменного тока
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod = 1e9 + 7;
const int maxn = 1e6 + 5;
ll _pow(ll a, ll b){
ll ans = 1;
while(b){
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
int main(){
int n; cin >> n;
ll ans = 0;
for(int i = 2; i <= n; i ++){
ans = (ans + _pow(26, i) - (i * _pow(25, i - 1) % mod + _pow(25, i)) % mod + mod) % mod;
}
cout << ans << endl;
return 0;
}
J Группа лягушек квакать квакать квакать квакать
Тема
- Есть n сеток, и каждая сетка имеет номер 1, 2, 3, 4 ... n
- Затем Ню Ню выпустил бесконечных лягушек. Маршрут i-й лягушки представляет собой геометрическую последовательность с первым членом, равным 1, и знаменателем p (i), где p (i) представляет собой i-е простое число.
- Когда лягушка прыгает на сетку, если на ней есть число, лягушка съест это число.
- Спросите, какое наименьшее общее кратное всех оставшихся чисел, которые не были съедены, и возьмите модуль 1e9 + 7.
- Диапазон 1≤n≤1.6e8, ограничение по времени 2 с
Идеи
- Для числа n первая единица определенно будет съедена, а затем, если после разложения на простые множители останется только один простой множитель, она определенно будет съедена, поэтому условием выживания является то, что она может разложить более одного простого множителя.
- Тогда есть теорема lcm, такая как lcm трех чисел x, y, z, после разложения на простые множители соответственно x = p1 ^ a1 * p2 ^ b1 * p3 ^ c1, y = p1 ^ a2 * p2 ^ b2 * p3 ^ c3, z = p1 ^ a3 * p2 ^ b3 * p3 ^ c3, тогда lcm = p1 ^ (max (a1, a2, a3)) * p2 ^ (max (b1, b2, b3)) * p3 ^ ( max (c1, c2, c3)) , поэтому при поиске простых множителей нам также необходимо найти наиболее разложенную величину
- Итак, мы должны сначала просеять простые числа, и здесь используется решето Эйлера .
- Тогда как мы можем разложить большее количество? Если в это время простой множитель равен 2, то, чтобы получить дополнительный простой множитель, найдите меньшее 3, а затем умножьте наибольшее число 2 на 3, и результат умножения не будет превосходит n; если это другой простой множитель ci, то вы можете найти 2 и умножить наиболее вычисленное ci на 2, и результат умножения не превосходит n. Наконец, умножение разумного простого множителя - это 1см.
код переменного тока
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 8e7 + 5; //给的上限的一半
const int mod = 1e9 + 7;
int v[N], prime[N], cnt = 0;
void get_prime(){ //欧拉筛
for(int i=2;i<=N;i++){
if(!v[i]){
v[i]=i;prime[++cnt]=i;
}
for(int j=1;j<=cnt&&i*prime[j]<=N;j++){
if(prime[j]>v[i])break;
v[i*prime[j]]=prime[j];
}
}
}
int main(){
get_prime();
int n; scanf("%d", &n);
if(n < 6){ //小于6的都会被吃
puts("empty");
return 0;
}
ll cc = 0, dd = 2; //质因子是2的另算,cc是能取2的最多数量
while(dd * 3 <= n) dd *= 2, cc ++;
ll ans = 1;
while(cc --) ans = (ans * 2) % mod; //cc个2相乘,就是pi^ai,最后lcm就是这些算式的乘积
for(int i = 2; i <= cnt && prime[i] * 2 <= n; i ++){
cc = 0, dd = prime[i];
while(dd * 2 <= n) dd *= prime[i], cc ++; //同理,其他质因子要与2配对,找最大的数量
while(cc --) ans = ans * prime[i] % mod;
}
printf("%lld\n", ans);
return 0;
}