2021 Niu Ke Winter Holiday Algorithm Basic Training Camp 1 A-string (수학 공식) J 작은 개구리 그룹 꽥꽥 꽥꽥 꽥꽥 (LCM)

주제 링크 : A-string   J 작은 개구리 그룹

A- 문자열

이야기

  • n 이하이고 하위 시퀀스 "us"를 포함하는 소문자로 구성된 문자열은 몇 개입니까? 답은 모듈로 1e9 + 7입니다.
  • 하위 시퀀스, 우리는 인접하지 않을 수 있습니다.
  • 범위 : 2≤n≤1e6

아이디어

  • 수학 공식. dp 푸시 상태를  보려면 여기를 클릭하세요 ~
  • 난이도는 반대 입니다. n이 3과 같이 us 하위 시퀀스를 포함하지 않는 것을 찾습니다.
  1. 세 가지 모두에 대해 s를 선택하지 않고 총 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을 선택하고 us 하위 시퀀스를 포함하지 않는 25 ^ 2 * 3 + 25 ^ 3을 제거한 다음 나머지는 us 하위 시퀀스를 포함합니다.
  • 따라서 길이가 n 인 문자열의 경우 하위 시퀀스의 수는 26 ^ n-25 ^ (n-1) * n + 25 ^ n이고 뺄셈을 mod에 더한 다음 modulo를 추가해야합니다.

ac 코드

#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이라는 숫자가 있습니다.
  • 그런 다음 Niu Niu는 끝없는 개구리를 방출했습니다 . i 번째 개구리의 경로는 첫 번째 항이 1이고 공통 비율 p (i)가있는 기하학적 시퀀스입니다. 여기서 p (i)는 i 번째 소수를 나타냅니다.
  • 개구리가 그리드로 점프 할 때 그리드에 숫자가 있으면 개구리가 숫자를 먹습니다.
  • 먹지 않은 나머지 모든 숫자의 최소 공배수가 얼마인지 묻고 1e9 + 7의 계수를 취하십시오.
  • 범위 1≤n≤1.6e8, 시간 제한 2s

아이디어

  • 숫자 n의 경우 처음 1 개는 반드시 먹게되고, 소인수 분해 후 소인수가 하나만 있으면 반드시 먹게되므로 하나 이상의 소인수를 분해 할 수있는 것이 생존 조건입니다.
  • 그러면 각각 소인수 x = p1 ^ a1 * p2 ^ b1 * p3 ^ c1, y = p1 ^ a2 * p2 ^ b2 * 세 숫자 x, y, z의 lcm과 같은 lcm의 정리가 있습니다. 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을 초과하지 않습니다. 마지막으로 합리적인 소인수를 곱하면 lcm이됩니다.

ac 코드

#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