×

20261009做题记录

上午模拟赛

T1:显然有 $$f(x^n) = \Pi (n\times c_i + 1)$$, 其中 \(x = \Pi p_i^{c_i}\),然后做酒枚举每个质数,然后看它对它的倍数的贡献就可以了,时间复杂度 \(O(\sqrt r \log \log r)\)。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define N 1000005
#define intl long long
#define mod (1000000007)
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
    intl x=0,k=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*k;
}
intl l,r,n,a[N],b[N],vis[N];
vector<intl> prim;
void init() {
    For(i,2,N-5) {
        if(!vis[i]) prim.push_back(i);
        for(auto x:prim){
            if(i*x>N-5) break;
            vis[i*x]=1;
            if(i%x==0) break;
        }
    }
}
int main() {
    l=read(), r=read(), n=read();
    init();
    For(i,0,r-l) a[i]=l+i, b[i]=1;
    for(auto p:prim){
        intl qwe=(l+p-1)/p*p;
        for(intl x=qwe;x<=r;x+=p) {
            intl pos=x-l,cnt=0;
            while(a[pos]%p==0) a[pos]/=p, cnt++;
            (b[pos] *= (n*cnt+1)) %= mod;
        }
    }
    intl ans = 0;
    For(i,0,r-l) {
        if(a[i] > 1) (b[i] *= (n+1)) %= mod;
        (ans += b[i]) %= mod;
    }
    printf("%lld\n",ans);
    return 0;
}

T2:显然,\(f_{py} = 1 + f_y + \lceil \frac{x-py}{k} \rceil, y \in Z\),我们考虑只需要让 \(y = \lfloor \frac{x}{p} \rfloor\)。

证明

令 \(n = \lfloor \frac{x}{p} \rfloor,q = n - d, r = x - pn\),那么有
$$ f_q + \lceil \frac{x-qy}{k} \rceil = f_q + \lceil \frac{x-np+dp}{k} \rceil \ge \ f_q + \lceil \frac{r}{k} \rceil + d \ge f_n + \lceil \frac{r}{k} \rceil $$,因为 \(f_n \le f_q + d\) 所以不等式成立。
故这么搜索就可以了。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define N 1000005
#define intl long long
#define mod (1000000007)
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
    intl x=0,k=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*k;
}
intl l,r,n,a[N],b[N],vis[N];
vector<intl> prim;
void init() {
    For(i,2,N-5) {
        if(!vis[i]) prim.push_back(i);
        for(auto x:prim){
            if(i*x>N-5) break;
            vis[i*x]=1;
            if(i%x==0) break;
        }
    }
}
int main() {
    l=read(), r=read(), n=read();
    init();
    For(i,0,r-l) a[i]=l+i, b[i]=1;
    for(auto p:prim){
        intl qwe=(l+p-1)/p*p;
        for(intl x=qwe;x<=r;x+=p) {
            intl pos=x-l,cnt=0;
            while(a[pos]%p==0) a[pos]/=p, cnt++;
            (b[pos] *= (n*cnt+1)) %= mod;
        }
    }
    intl ans = 0;
    For(i,0,r-l) {
        if(a[i] > 1) (b[i] *= (n+1)) %= mod;
        (ans += b[i]) %= mod;
    }
    printf("%lld\n",ans);
    return 0;
}
T3:显然,$V$ 的上限 $V+H$,我们直接做一个背包,时间复杂度为 $O(nH(H+V))$,然后就做完了,只需要找最大值就可以了。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define N 1005
#define intl long long
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
    intl x=0,k=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*k;
}
intl n, H, V, h[N], v[N], w[N], dp[N][N+N];
int main() {
    n = read(), H = read(), V = read();
    For(i,1,n) h[i] = read(), v[i] = read(), w[i] = read();
    memset(dp, -1, sizeof dp);dp[0][0] = 0;
    For(i,1,n) deo(j,H,h[i]) deo(k,H+V,v[i]) if(dp[j-h[i]][k-v[i]] != -1)
        dp[j][k] = max(dp[j][k], dp[j-h[i]][k-v[i]] + w[i]);
    intl ans = 0;
    For(i,0,H) For(j,0,H+V) dp[i][j] = max({dp[i-1<0?0:i-1][j], dp[i][j-1<0?0:j-1], dp[i][j]});
    For(x, 0, H) ans = max(ans, dp[H-x][V+x]);
    printf("%lld\n", ans); 
    return 0;
}
 
T4:显然,考虑线段树,我们发现我们可以将修改分为三种:
  1. \(i\in[l,r]\) 直接线段树覆盖区间最大值就可以了。
  2. \(i\in[1,l-1]\) 我们发现可以转化为 \(p+i-l\),然后令 \(p-l\) 为 \(c\),对于线段树上的一个点 \(k\),他这个区间的最大值就是 \(c+k_r\),\(tag_k = \max(tag_k, c)\),下传即可。
  3. \(i\in[r+1,n]\) 发现就是和第二种一样,只不过是 \(p+r-i\),我们令 \(c = p+r\),那么对于线段树上的一个点最大值有 \(c - k_l\), \(tag_k = \max(tag_k, c)\),下传即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define N 500005
#define intl long long
#define inf (-4485090715960753727ll)
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
	intl x=0,k=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
	while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*k;
}
struct Seg{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid ((l+r)>>1)
	intl tr[N<<2], tag[3][N<<2];
	Seg() {
		memset(tr, 0, sizeof tr), memset(tag, -0x3f, sizeof tag);
	}
	void apply(intl p,intl l,intl r,intl d,intl op) {
//		if(r == 1) cout << d <<" " << op << endl;
		tr[p] = max(tr[p], op == 1?d+r:(op==2?d:d-l));
		tag[op][p] = max(tag[op][p], d);
	}
	void pushdown(intl p,intl l,intl r) {
		For(i,0,2) if(tag[i][p] != inf) apply(lc, l, mid, tag[i][p], i), apply(rc,mid+1,r,tag[i][p], i), tag[i][p] = inf;
	}
	void updata(intl p,intl l,intl r,intl ll,intl rr,intl d,intl op) {
//		cout << p << " " << ll << " " << rr << endl;
		if(rr < ll) return ;
		if(rr < l || r < ll) return ;
		if(ll <= l && r <= rr) return apply(p, l, r, d, op), void();
		pushdown(p, l, r);
		updata(lc, l, mid, ll, rr, d, op), updata(rc, mid+1, r, ll, rr, d, op);
		tr[p] = max(tr[lc], tr[rc]);
	}
	intl query(intl p,intl l,intl r,intl ll,intl rr) {
		if(rr < l || r < ll) return 0ll;
		if(ll <= l && r <= rr) return tr[p];
		pushdown(p, l, r);
		return max(query(lc, l, mid, ll, rr) , query(rc, mid+1, r, ll, rr));
	}
}seg;
intl n, q;
int main() {
//	cout << seg.tag[1][1] << endl;
	n = read(), q = read();
	while(q --) {
		intl op = read(), l = read(), r = read();
		if(op == 1) {
			intl p = read();
			seg.updata(1,1,n,l,r,p,2);
			seg.updata(1,1,n,max(1ll,l-p),l-1,p-l,1);
			seg.updata(1,1,n,r+1,min(n,r+p),p+r,0);
		} else printf("%lld\n", seg.query(1,1,n,l,r));
	}
	return 0;
}
/*
10 7
1 3 5 3
2 4 4
2 6 10
1 5 7 4
2 1 1
2 2 3
2 1 10
*/

posted @ 2026-10-09 11:52  shiori123  阅读(1)  评论(0)    收藏  举报