玄关求好心人卡常
  • 板块学术版
  • 楼主小超手123
  • 当前回复11
  • 已保存回复11
  • 发布时间2024/7/31 20:21
  • 上次更新2024/7/31 21:45:38
查看原帖
玄关求好心人卡常
490978
小超手123楼主2024/7/31 20:21
#include <bits/stdc++.h>
#define int long long
#define N 100005
#define mod 998244353
using namespace std;

#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf;

int read() {
    int p = 0, flg = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') flg = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        p = p * 10 + c - '0';
        c = getchar();
    }
    return p * flg;
}

void print(int x) {
	if(x < 0) putchar('-'), x = -x;
	if(x > 9) print(x / 10);
	putchar('0' + x % 10);
}

int n, Sum; //Sum琛ㄧず鎬荤殑鏂规鏁?
int a[N], ans[N];

struct Tree {
    int c[N * 4], tag1[N * 4], tag2[N * 4]; //tag1璧嬪€? tag2鍔?

    void init() {
        memset(c, 0, sizeof(c));
        memset(tag1, 0, sizeof(tag1)); 
        memset(tag2, 0, sizeof(tag2)); 
    }

    void pushup(int u) {
        c[u] = (c[u * 2] + c[u * 2 + 1]) % mod;
    }

    void maketag(int u, int L, int R, int tg1, int tg2) {
        if(tg1 != -1) {
            tag1[u] = tg1;
            tag2[u] = tg2;
            c[u] = (tg1 + tg2) * (R - L + 1) % mod;
        }
        else {
            tag2[u] = (tag2[u] + tg2) % mod;
            c[u] = (c[u] + tg2 * (R - L + 1) % mod) % mod;
        }
    }

    void pushdown(int u, int L, int R) {
        if(tag1[u] == -1 && tag2[u] == 0) return;
        int mid = (L + R) / 2;
        maketag(u * 2, L, mid, tag1[u], tag2[u]);
        maketag(u * 2 + 1, mid + 1, R, tag1[u], tag2[u]);
        tag1[u] = -1; tag2[u] = 0;
    }

    void update(int u, int L, int R, int l, int r, int x, int y) { //[l,r]=x 鎴?[l,r]+=y
        if(R < l || r < L) return;
        if(l <= L && R <= r) {
            maketag(u, L, R, x, y);
            return;
        }
        int mid = (L + R) / 2;
        pushdown(u, L, R);
        update(u * 2, L, mid, l, r, x, y);
        update(u * 2 + 1, mid + 1, R, l, r, x, y);
        pushup(u);
    }

    int query(int u, int L, int R, int l, int r) {
        if(R < l || r < L) return 0;
        if(l <= L && R <= r) return c[u];
        int mid = (L + R) / 2;
        pushdown(u, L, R);
        return (query(u * 2, L, mid, l, r) + query(u * 2 + 1, mid + 1, R, l, r)) % mod;
    }
}t1, t2; //f[i]鐨勫墠缂€鍜? f[i]*i鐨勫墠缂€鍜?

struct node {
    int l, r, i, z; //宸︾鐐规墍灞炵殑鍖洪棿涓?[l,r]锛屽彸绔偣涓?i锛実cd 涓?z銆?
};
vector<node>t, now;

bool cmp(node A, node B) {
    if(A.z != B.z) return A.z < B.z;
    else return A.i < B.i;
}

int Gcd[N][25], lg[N];

int Get_gcd(int L, int R) {
    int h = lg[R - L + 1];
    return __gcd(Gcd[L][h], Gcd[R - (1 << h) + 1][h]);
}

int ask(int x) {
    if(x <= 0) return 0;
    return ((x + 1) * t1.query(1, 1, n, x, x) % mod - t2.query(1, 1, n, x, x) + mod) % mod; 
}

unordered_map<int, int>h; //鎶婃瘡绉岹CD鐩稿悓鐨勭紪涓彿 
int cnt;

struct ljm {
    int opt, i, x; //opt=1:f opt=2:g  f[i]=x
};
vector<ljm>B[N * 35];
int tiao[N];
void work(int Gcd, int opt) { //鎶奊cd鐩稿悓鐨勫鐞?
    t1.update(1, 1, n, 1, n, 0, 0);
    t2.update(1, 1, n, 1, n, 0, 0);
    
    if(!h[Gcd]) {
    	h[Gcd] = ++cnt;
		tiao[cnt] = Gcd;
	}
    Gcd = h[Gcd];

    for(auto x : now) {
        int res = ask(x.r - 1) - ask(x.l - 2) + (x.r - x.l + 1);
		t1.update(1, 1, n, x.i, n, -1, res);
        t2.update(1, 1, n, x.i, n, -1, res * x.i % mod);
        if(opt == 1) B[Gcd].push_back((ljm){1, x.i, res});
        else B[Gcd].push_back((ljm){2, n - x.i + 1, res});
        if(opt == 1) Sum = (Sum + res) % mod;
    }
}

void Sol(int opt) {
    t1.init(); t2.init();
    t.clear();
    for(int i = 2; i <= n; i++) lg[i] = lg[i / 2] + 1;
    for(int i = 1; i <= n; i++) Gcd[i][0] = a[i];
    for(int j = 1; j <= 20; j++)
    for(int i = 1; i + (1 << j) - 1 <= n; i++) Gcd[i][j] = __gcd(Gcd[i][j - 1], Gcd[i + (1 << (j - 1))][j - 1]);

    //cout << "look : " << Get_gcd(1, 5) << endl;

    for(int i = 1; i <= n; i++) {
        int r = i, l;
        while(r) {
            int res = Get_gcd(r, i);
            int L = 1, R = r, Get = 0, mid;
            while(L <= R) {
                mid = (L + R) / 2;
                if(Get_gcd(mid, i) >= res) {
                    Get = mid;
                    R = mid - 1;
                }
                else L = mid + 1;
            }
            l = Get;
            t.push_back((node){l, r, i, res});
            //if(res == 2) 
			//printf("l = %lld, r = %lld, i = %lld, res = %lld \n", l, r, i, res);
            r = l - 1;
        }
    }

    sort(t.begin(), t.end(), cmp);
    int L = 0;
    while(L < t.size()) {
        now.clear();
        int R = L;
        now.push_back(t[L]);
        while(R + 1 < t.size() && t[R + 1].z == t[L].z) now.push_back(t[++R]);
        //if(t[L].z == 2)
		work(t[L].z, opt);
        L = R + 1;
    }
}

bool cmp2(ljm a, ljm b) {
    return a.i < b.i;
}
int v[N], F[N], G[N], len;
void Get_ans(int x) {
	
    sort(B[x].begin(), B[x].end(), cmp2);
    
    /*printf("Gcd = %lld : \n", tiao[x]);
	for(auto now : B[x]) {
		if(now.opt == 1) printf("f[%lld] = %lld \n", now.i, now.x);
		else printf("g[%lld] = %lld \n", now.i, now.x);
	}*/
	//printf("\n");
	
    len = 0;
    int lst = 0;
    for(auto now : B[x]) {
        if(now.i == lst) {
            if(now.opt == 1) F[len] += now.x;
            else G[len] += now.x; 
        }
        else {
            lst = now.i;
            v[++len] = now.i;
            if(now.opt == 1) F[len] += now.x;
            else G[len] += now.x; 
        }
    }

    for(int i = 1; i <= len; i++) F[i] = (F[i] + F[i - 1]) % mod;
    for(int i = len; i >= 1; i--) G[i] = (G[i] + G[i + 1]) % mod;

    for(int i = 0; i <= len; i++) {
    	int L = v[i] + 1, R;
    	if(i == len) R = n;
    	else R = v[i + 1] - 1;
    	if(L <= R) {
    		int res = ((F[i] + 1) * (G[i + 1] + 1) % mod - 1 + mod) % mod;
    		ans[L] = (ans[L] + res) % mod;
    		ans[R + 1] = (ans[R + 1] - res + mod) % mod;
    		//printf("opt : [%lld, %lld] += %lld \n", L, R, res);
		}
	}
	for(int i = 1; i <= len; i++) {
		int res = ((F[i - 1] + 1) * (G[i + 1] + 1) % mod - 1 + mod) % mod;
		int L = v[i], R = v[i];
		ans[L] = (ans[L] + res) % mod;
    	ans[R + 1] = (ans[R + 1] - res + mod) % mod;
    	//printf("opt : [%lld, %lld] += %lld \n", i, i, res);
	}
	//printf("\n \n");

    for(int i = 1; i <= len; i++) v[i] = F[i] = G[i] = 0;
}

signed main() {
	//freopen("x.in", "r", stdin);
	//freopen("x.out", "w", stdout);
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);

    n = read();
    for(int i = 1; i <= n; i++) a[i] = read();
   	//cerr << "e";
	Sol(1); 
	reverse(a + 1, a + n + 1);
    Sol(2);

    for(int i = 1; i <= cnt; i++) Get_ans(i);
    for(int i = 1; i <= n; i++) ans[i] = (ans[i - 1] + ans[i]) % mod;
    //cerr << "Sum : " << Sum << endl;
    //Sum = 24;
    
    for(int i = 1; i <= n; i++) {
    	print((Sum - ans[i] + mod) % mod);
    	printf(" ");
	}
    return 0;
}

/*
6
3 6 12 2 4 1
*/ 
2024/7/31 20:21
加载中...