Educational Codeforces Round 138 D

D. Counting Arrays

我们对于每一个找合法序列是多少显然很麻烦
我们直接找不合法的
显然对于i个位置上 他不能是前面lcm(1,2,3...i-1)的倍数才可以
显然我们这里面 lcm(只能有质因数构成)也就是最小的 不然可能会漏解
不然我们可以通过一直删第一个位置 让他又变成一个合法的序列
所以我们直接对于每一个i找出有多少个数不合法 然后与i-1的方案乘法原理
再用总的方案-不合法方案即可
注意 m就大于mod了 只要出现了m就要注意取模

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5+10;
const int M = 998244353;
const int mod = 998244353;
#define int long long
int up(int a,int b){return a<0?a/b:(a+b-1)/b;}
#define endl '\n'
#define all(x) (x).begin(),(x).end()
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define _ 0
#define pi acos(-1)
#define INF 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int st[N],primes[N],cnt=0;
void init() {
    for(int i = 2 ; i < N ; i ++ ) {
        if(!st[i]) primes[cnt ++ ] = i;
        for(int j = 0; primes[j] * i < N ; j ++ ) {
            st[primes[j] * i] = true;
            if(i % primes[j] == 0) break;
        }
    }
}
int lcm(int a, int b) {
    return a * b / __gcd(a, b);
}
int qpow(int a,int k,int p){
    int res=1;
    while(k){
        if(k&1)res=res*a%p;
        k>>=1;
        a=a%p*a%p;
    }
    return res;
}
void solve() {
    init();
    int n,m;cin>>n>>m;
    int sum=1,ans=0,lc=1;
    for(int i=1;i<=n;i++)(ans+=qpow(m%mod,i,mod))%=mod;
    for(int i=1;i<=n;i++){
        if(!st[i])lc=lcm(lc,i);
        (sum*=(m/lc)%mod)%=mod;
        (ans-=sum)%=mod;
        (ans+=mod)%=mod;
    }
    cout<<(ans+mod)%mod<<endl;
}
signed main(){
    fast
    int t;t=1;//cin>>t;
    while(t--) {
        solve();
    }
    return ~~(0^_^0);
}
posted @ 2022-10-22 23:45  ycllz  阅读(23)  评论(0)    收藏  举报