2021 Niu Ke Winter Holiday Алгоритм Базовый тренировочный лагерь 1 A-строка (математическая формула) J Группа маленьких лягушек, шарлатан, шарлатан, шарлатан, шарлатан (LCM)

Ссылка на тему: A-String   J Группа лягушек квакать квакать квакать квакать

Строка

Тема

  • Сколько строк состоит из строчных букв не более n и содержит подпоследовательность «us»? Ответ - по модулю 1e9 + 7.
  • Последовательность, нас не может быть рядом
  • Диапазон: 2≤n≤1e6

Идеи

  • Математические формулы. Если вы хотите увидеть статус dp push,  нажмите здесь ~
  • Сложность обратная: найдите ту, которая не содержит подпоследовательности us, например, n равно 3.
  1. Выберите "нет" для всех трех, а затем всего 25 * 25 * 25
  2. Последний - s, затем u нельзя выбрать раньше, всего 25 * 25 * 1
  3. Второй выбирает s, затем предпоследний не может выбрать s, потому что он будет повторяться с 2, а первый не может быть u, всего 25 * 1 * 25
  4. Первый выбирает 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;
}

 

рекомендация

отblog.csdn.net/weixin_43911947/article/details/113530909
рекомендация