주제 링크 : A-string J 작은 개구리 그룹
A- 문자열
이야기
- n 이하이고 하위 시퀀스 "us"를 포함하는 소문자로 구성된 문자열은 몇 개입니까? 답은 모듈로 1e9 + 7입니다.
- 하위 시퀀스, 우리는 인접하지 않을 수 있습니다.
- 범위 : 2≤n≤1e6
아이디어
- 수학 공식. dp 푸시 상태를 보려면 여기를 클릭하세요 ~
- 난이도는 반대 입니다. n이 3과 같이 us 하위 시퀀스를 포함하지 않는 것을 찾습니다.
- 세 가지 모두에 대해 s를 선택하지 않고 총 25 * 25 * 25를 선택합니다.
- 마지막 것은 s이고 u는 이전에 선택할 수 없으며 총 25 * 25 * 1입니다.
- 두 번째 사람은 s를 선택하면 두 번째 사람은 s를 선택할 수 없습니다. 2로 반복되고 첫 번째 사람은 u가 될 수 없으므로 총 25 * 1 * 25입니다.
- 첫 번째 사람이 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;
}