Codeforces Round #447 (Div. 2)

A

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

string st;

int main(){
	//freopen("in.txt","r",stdin);
	cin>>st;
	int cnt=0;
	for(int i=0;i<(int)st.size();i++)
		for(int j=i+1;j<(int)st.size();j++)
			for(int k=j+1;k<(int)st.size();k++)
				if(st[i]=='Q'&&st[j]=='A'&&st[k]=='Q')
					cnt++;
	cout<<cnt;
	return 0;
}

B

猜结论。。。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

ll n,m,k;

inline ll power(ll a,ll n,ll p){
	ll ret=1;ll now=a;
	while(n!=0){
		if(n&1)
			ret=ret*now%p;
		now=now*now%p;
		n>>=1;
	}
	return ret;
}

int main(){
	//freopen("in.txt","r",stdin);
	cin>>n>>m>>k;
	if(((n+m)&1)&&k==-1)
		puts("0");
	else {
		ll res = power(2,n-1,1000000007);
		res = power(res,m-1,1000000007);
		cout<<res;
	}
	return 0;
}

C

提供了一个假算法,惨遭hack。正解构造。
如果整个数列的最大公约数是最小的那个数字,那么可以构造出一个数列,只需要让每个数字中间夹着一个a[0] 就可以让区间长度大于等于二的区间的最大公约数为a[0]。

#include <stdio.h>
int n,a[1005];
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%d",a+i);
	bool flg=1;
	for(int i=0;i<n;i++) if(a[i]%a[0]) flg=0;
	if(!flg) printf("-1");
	else {printf("%d
",2*n);for(int i=0;i<n;i++) printf("%d %d ",a[i],a[0]);}
	return 0;
}

D

预处理出每个子树,每个点到该子树的根的距离,排个序。复杂度$O(n log n log n)$
然后对于每个询问,每次向上爬就行了。复杂度$O(m log n log n)$。

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
vector<int> dis[maxn];
vector<ll> sum[maxn];
int n, m, A;
ll H;
int L[maxn];
int cnt;

template<typename T> inline void read(T &x) {
	x = 0; T f = 1; char ch; do {ch = getchar(); if (ch == '-')f = -1;} while (ch < '0' || ch > '9'); do x = x * 10 + ch - '0', ch = getchar(); while (ch <= '9' && ch >= '0'); x *= f;
}

template<typename A, typename B> inline void read(A&x, B&y) {read(x); read(y);}
template<typename A, typename B, typename C> inline void read(A&x, B&y, C&z) {read(x); read(y); read(z);}
template<typename A, typename B, typename C, typename D> inline void read(A&x, B&y, C&z, D&w) {read(x); read(y); read(z); read(w);}

void dfs(int id) {
	dis[id].pb(0);
	if (id * 2 > n) {
		return;
	} else if (id * 2 + 1 > n) {
		int l = id * 2;
		dfs(l);
		for (auto d : dis[l]) {
			dis[id].pb(d + L[l]);
		}
	} else {
		int l = id * 2, r = id * 2 + 1;
		dfs(l);
		for (auto d : dis[l]) {
			dis[id].pb(d + L[l]);
		}
		dfs(r);
		for (auto d : dis[r]) {
			dis[id].pb(d + L[r]);
		}
	}
}

ll get(int A, ll H) {
	int id = upper_bound(dis[A].begin(), dis[A].end(), H) - dis[A].begin();
	if (!id) return 0;
	return H * id - sum[A][id - 1];
}

int main() {
	//freopen("in.txt","r",stdin);
	read(n, m);
	for (int i = 2; i <= n; i++)
		read(L[i]);
	dfs(1);
	for (int i = 1; i <= n; i++)
		sort(dis[i].begin(), dis[i].end());
	for (int i = 1; i <= n; i++) {
		ll tmp = 0;
		for (int j = 0; j < (int)dis[i].size(); j++) {
			tmp += dis[i][j];
			sum[i].pb(tmp);
		}
	}
	ll xres;
	while (m--) {
		read(A, H);
		ll res = 0;
		res += xres = get(A, H);
		//cout<<"#"<<xres<<endl;
		int lst = A;
		int now = A / 2;
		while (now) {
			H -= L[lst];
			if (H < 0) break;
			res += H;
			if (lst & 1) {
				if (H >= L[now * 2]) {
					res += xres = get(now * 2, H - L[now * 2]);
					//cout<<"#"<<xres<<endl;
				}
			} else {
				if (H >= L[now * 2 + 1]) {
					res += xres = get(now * 2 + 1, H - L[now * 2 + 1]);
					//cout<<"#"<<xres<<endl;
				}
			}
			lst = now;
			now = now / 2;
		}
		printf("%I64d
", res);
	}
	return 0;
}

E

首先,强连通分量中的每条边是都可以走"完"的。
对于边权w,可以二分一个最大的p,满足$w-1-2-...-p>=0$,此时的贡献为$w(p+1)-frac{p(p+1)(p+2)}{6}$.
缩点之后做一次dag上的dp。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
const int maxm = 1e6+5;

template<typename T> inline void read(T &x){
x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
}

template<typename A,typename B> inline void read(A&x,B&y){read(x);read(y);}
template<typename A,typename B,typename C> inline void read(A&x,B&y,C&z){read(x);read(y);read(z);}
template<typename A,typename B,typename C,typename D> inline void read(A&x,B&y,C&z,D&w){read(x);read(y);read(z);read(w);}

struct node{
	int v;ll w;
	node(){}
	node(int _v,ll _w):v(_v),w(_w){}
};
vector<node> e[maxn];
int Low[maxn],DFN[maxn],Stack[maxn],Belong[maxn];
int num[maxn];
int Index,top,n,m,x,y;
ll z;
int scc;
bool Instack[maxn];
ll score[maxn];
vector<int> scce[maxn];
ll dp[maxn];

void Tarjan(int u){
	int v;
	Low[u]=DFN[u]=++Index;
	Stack[top++]=u;
	Instack[u]=true;
	for(auto enxt:e[u]){
		v=enxt.v;
		if(!DFN[v]){
			Tarjan(v);
			Low[u]=min(Low[u],Low[v]);
		} else if(Instack[v] && Low[u]>DFN[v])
			Low[u]=DFN[v];
	}
	if(Low[u]==DFN[u]){
		scc++;
		do{
			v=Stack[--top];
			Instack[v]=false;
			Belong[v]=scc;
			num[scc]++;
		}while(v!=u);
	}
}
int indeg[maxn],outdeg[maxn];

ll calc(ll w){
	ll l=0,r=1e6+5,rt;
	while(l<=r){
		ll mid=(l+r)/2;
		if(mid*(mid+1)/2<=w)
			l=(rt=mid)+1;
		else r=mid-1;
	}
	ll ret=w*(rt+1ll)-rt*(rt+1ll)*(rt+2ll)/6ll;
	return ret;
}

inline void solve(int n){
	memset(DFN,0,sizeof DFN);
	memset(num,0,sizeof num);
	memset(Instack,0,sizeof Instack);
	Index=scc=top=0;
	for(int i=1;i<=n;i++) if(!DFN[i]) Tarjan(i);
	memset(indeg,0,sizeof indeg);
	memset(outdeg,0,sizeof outdeg);
	for(int u=1;u<=n;u++)
		scce[Belong[u]].push_back(u);
	for(int u=1;u<=n;u++)
		for(auto enxt:e[u]){
			int v=enxt.v;
			if(Belong[u]!=Belong[v]){
				outdeg[Belong[u]]++;
				indeg[Belong[v]]++;
			} else {
				score[Belong[u]]+=calc(enxt.w);
			}
		}
}

ll find(int nowscc){
	if(dp[nowscc]!=-1) return dp[nowscc];
	ll ret = 0;
	for(auto u:scce[nowscc])
		for(auto enxt:e[u]){
			int v=enxt.v;
			if(Belong[u]==Belong[v]) continue;
			ll w=enxt.w;
			ret = max(ret,find(Belong[v])+w);
		}
	dp[nowscc]=(ret+score[nowscc]);
	return dp[nowscc];
}

int main(){
	//freopen("in.txt","r",stdin);
	read(n,m);
	for(int i=1;i<=m;i++){
		read(x,y,z);
		e[x].push_back(node(y,z));
	}
	solve(n);
	// printf("%d
",Belong[0]);
	// for(int i=1;i<=scc;i++){
	// 	for(auto ep:scce[i])
	// 		printf("%d ",ep);
	// 	puts("");
	// }
	memset(dp,-1,sizeof dp);
	int start;
	read(start);
	ll res = find(Belong[start]);
	cout<<res;
	return 0;
}
原文地址:https://www.cnblogs.com/foreignbill/p/7868714.html