ICPC南昌邀请赛(B、G) 拉格朗日插值、 缩点

B:https://nanti.jisuanke.com/t/40254

做两次插值,可以On得出a[n +1]的一项,然后前缀和,再做插值,针对每次查询,On处理


ll a[maxn];   
ll fac[maxn],invv[maxn],suf[maxn],pre[maxn]  ;
void Init(){
	fac[0] = 1;
	fac[1] = 1;
	for(int i = 2;i <= 2000;i++) fac[i] = fac[i - 1] * i,fac[i] %= mod; 
	for(int i = 0;i <= 2000;i++) invv[i] = inv(fac[i]);  
	return ;
} 
ll post[maxn];
ll calc(ll k,ll n){
	ll res = 0;
	pre[0] = k;/*
	for(int i = 1;i <= n;i++) mul2(pre[i],mul1(pre[i - 1],k - i));*/
	for(int i = 1;i <= n;i++) pre[i] = pre[i - 1] * (k - i),pre[i] %= mod;
	post[n] = k - n;  
	for(int i = n - 1;i >= 0;i--) post[i] = post[i + 1] * (k - i),post[i] %= mod ;
	for(int i = 0;i <= n;i++){ 
		ll num = invv[i] * invv[n - i] % mod;
		if((n - i) & 1) num = -num;
		if(i - 1 >= 0)
		num *= pre[i - 1];num %= mod;  
		if(i + 1 <= n)
		num *= post[1 + i],num %= mod;
		num *= a[i],num %= mod;
		res += num;   res += mod, res %= mod;
	}
	return res;
}  
 ll n,k;
int main()
{ 
	Init();
	ios; int t,q;cin >> t;while(t--){ 
		cin >> n >> q; 
		for(int i =0;i <= n;i++) cin >> a[i];  
		a[n + 1] = calc(n + 1,n);      
		for(int i = 1;i <= n + 1;i++){ 
			a[i] += a[i - 1];
			a[i] %= mod; 
		}  
		while(q--){
			ll l,r; cin >> l >> r; 
			ll val1 = calc(r,n + 1);
			ll val2 = calc(l - 1,n + 1);  
			wt((val1 - val2 + mod) % mod);
		} 
	}
    return 0;
}

G https://nanti.jisuanke.com/t/40259 

把所有的排序一下 ,然后建边,从高度高的指向低的(其实都一样,最后判断的时候修改一下也可以),缩点后,看看哪些点度数为0,他们就可能赢


 ll n,k; 
struct node{ 
	int id,val;
}g1[maxn],g2[maxn],g3[maxn];
bool cmp(node a,node b) { return a.val < b.val; }
std::vector v[maxn]; 
int cnt = 0; 
int col[maxn],val[maxn];
int tot;
int low[maxn],dfn[maxn],vis[maxn],in[maxn]; 
stacks; 
void tarjan(int u){ 
	low[u] = dfn[u] = ++tot;
	vis[u] = 1;s.push(u); 
	for(auto d:v[u]){ 
		if(!dfn[d]){ 
			tarjan(d);
			low[u] = min(low[u],low[d]);
		}else if(vis[d]) low[u] = min(dfn[d],low[u]);
	}
	if(low[u] == dfn[u]){ 
		int x ; cnt++; 
		do{ 
			x = s.top(); s.pop();vis[x] = 0; col[x] = cnt; 
		}while(x != u);
	} 
	return ;
} 
mapmp;
void create(int x){
	for(auto d:v[x]){ 
		int first = col[x],second = col[d];
		if(first == second) continue;
		if(!mp[P(first,second)]){   
			mp[P(first,second)] = 1;
			in[second]++;
		}
	}
}
int main()
{  	int q;
	while(cin >> n >> q){    
		cnt = 0 ,tot = 0;
		for(int i = 1;i <= n;i++) v[i].clear(),vis[i] = 0,in[i] = 0,col[i] = 0;
		for(int j = 1;j <= n;j++) scanf("%d",&g1[j].val),g1[j].id = j;  
		for(int j = 1;j <= n;j++) scanf("%d",&g2[j].val),g2[j].id = j;  
		for(int j = 1;j <= n;j++) scanf("%d",&g3[j].val),g3[j].id = j;  

		sort(rg(g1,1,n),cmp);
		sort(rg(g2,1,n),cmp);
		sort(rg(g3,1,n),cmp);
		for(int i = n;i >= 2;i--){ 
			v[g1[i].id] .pb(g1[i - 1].id);
		}
		for(int i = n;i >= 2;i--){ 
			v[g2[i].id] .pb(g2[i - 1].id);
		}
		for(int i = n;i >= 2;i--){ 
			v[g3[i].id] .pb(g3[i - 1].id);
		} 
		for(int i = 1;i <= n;i++) 
			if(!dfn[i])
				tarjan(i);
		for(int i = 1;i <= n;i++) create(i); 
			mapm; /*
		for(int i = 1;i <= n;i++) cout << in[i] << "  " ;
			cout << endl;*/
		for(int i = 1;i <= n;i++){ 
			if(!in[col[i]]) m[i] = 1; 
		}  
		while(q--){  
			int x;  
			scanf("%d",&x);
			if(m[x]) puts("YES");
			else puts("NO");
		}
	}
    return 0;
}
 

 

你可能感兴趣的:(ACM-ICPC,拉格朗日插值,强连通)