1. 程式人生 > >【0521模擬賽】小Z愛數學

【0521模擬賽】小Z愛數學

csu 復雜度 ace pan chan printf 排序 fine 個數

題目描述

小Z想求F(n,k),F(n,k)表示n的所有因數pi中,滿足n/pi <= k 的和。

小Z發現還是很水,所以他決定加大難度。

技術分享

小Z還準備了很多個詢問。現在你來解決一下吧。

輸入輸出格式

輸入格式:

第一行兩個整數m 表示詢問的個數

接下來每行兩個數ni,ki,表示這個詢問的n和k

輸出格式:

也就是把剛好等於k的答案加進去 然後k變大

對於每個詢問輸出一行一個整數,表示對應的答案。

題目理解:F(n,k)表示n的所有因數qi中,滿足n/qi<=k的和,

m組,每組給定n和k,求 技術分享

m<=500000,ni<=100000

解析:k比較大的的答案 包含了k比較小的答案,所以要先把每次詢問按k來排序,

然後我們每次回答詢問的時候 如果k不同 就把k變大成現在要問的k,

也就是把剛好等於k的答案插入線段樹, 然後k變大
復雜度 O (nlog^2n+mlogn) 代碼:
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 100000
#define ll long long
using namespace std;
inline int read(){
    
int x=0,f=1;char ch=getchar(); while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();} while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();} return x*f; } ll t[N*3],ans[N*5+10]; int m; struct que{int n,k,id;}e[N*5+10]; bool cmp(que i,que j){return i.k<j.k;} ll query(int l,int
r){ ll sum=0; l+=N-1,r+=N-1; sum+=t[l]+t[r]; if(l==r) return sum-=t[l]; for(;l^r^1;l>>=1,r>>=1){ if(~l&1) sum+=t[l^1]; if( r&1) sum+=t[r^1]; } return sum; } void Change(int x,int v){ t[x+=N-1]+=v; while(x) t[x>>=1]=t[x<<1]+t[x<<1|1]; } void sol(int x){ for(int i=1;i*x<=N;i++) Change(i*x,i); } int main(){ m=read(); for(int i=1;i<=m;i++){e[i].n=read();e[i].k=read();e[i].id=i;} sort(e+1,e+m+1,cmp); int j=0; for(int i=1;i<=m;i++){ while(j<e[i].k) sol(++j); ans[e[i].id]=query(1,e[i].n); } for(int i=1;i<=m;i++) printf("%lld\n",ans[i]); return 0; }

【0521模擬賽】小Z愛數學