2021 Niu Ke Winter Holiday Algorithm Basic Training Camp 1 A-string(数式)J小さなカエルのグループquack quack quack quack(LCM)

トピックリンク:A-   stringJ小さなカエルのグループcroakcroak croak croak

文字列

トピック

  • n以下で、サブシーケンス「us」を含む小文字で構成される文字列はいくつありますか?答えはモジュロ1e9 + 7です。
  • サブシーケンス、私たちは隣接していない可能性があります
  • 範囲:2≤n≤1e6

アイデア

  • 数式。dp pushのステータスを確認するには、 ここをクリックしてください〜
  • 難易度は反対です。nが3に等しいなど、usサブシーケンスを含まないものを見つけます。
  1. 3つすべてにsを選択しない場合は、合計25 * 25 * 25を選択します。
  2. 最後の1つはsで、uは前に選択できず、合計25 * 25 * 1です。
  3. 2番目のものはsを選択し、最後から2番目のものはsを選択できません。これは、2で繰り返され、最初のものはuにすることができないため、合計25 * 1 * 25
  4. 最初のものはsを選択し、2番目も最後もsを選択できません。これは、前のものと繰り返されるため、合計1 * 25 * 25です。
  • 26 ^ 3をランダムに選択し、usサブシーケンスを含まない25 ^ 2 * 3 + 25 ^ 3を削除してから、残りにusサブシーケンスを含めます。
  • したがって、長さnの文字列の場合、usサブシーケンスの数は26 ^ n-25 ^(n-1)* n + 25 ^ nであり、減算をmodで加算してからモジュロで加算する必要があります。

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小さなカエルのグループcroakcroak croak croak

トピック

  • n個のグリッドがあり、各グリッドには1、2、3、4 ... nの番号があります。
  • その後、ニウニウは無限のカエルをリリースしましたi番目のカエルのルートは、最初の項が1で、共通の比率がp(i)である等比数列です。ここで、p(i)はi番目の素数を表します。
  • カエルがグリッドにジャンプするとき、グリッドに数字がある場合、カエルはその数字を食べます
  • 食べられていない残りのすべての数の最小公倍数を尋ね、1e9 +7の係数を取ります
  • 範囲1≤n≤1.6e8、制限時間2秒

アイデア

  • 数nの場合、最初の1は必ず食べられ、素因数を分解した後に素因数が1つしかない場合は必ず食べられるので、生存の条件は複数の素因数を分解できることです。
  • 次に、素因数をそれぞれ分解した後、3つの数x、y、zのlcmなどのlcmの定理があります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を超えません。最後に、妥当な素因数を掛けると、その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