hihoCoder挑战赛22 笔记

第一题描述

小h很多朋友。他给第i个朋友分配了一个代号Ai,并使代号序列满足如下关系:

A= (k* Ai-1 + k* Ai-2) mod 1,000,000,007

现在小h忘记了第z个朋友的代号Az,但是他记得第x个朋友和第y个朋友的代号Ax和Ay

小h很着急,向小y求助。小y很忙,把任务交给了你,希望你求出第z个朋友的代号。  

输入

第一行共2个整数,k1,k2

第二行共4个整数,x,y,Ax,Ay

第三行共1个整数,z。

3<=x,y,z<=1018   0<=k1,k2<=105

输入数据保证有解,且解唯一

输出

共一行1个整数,Az

样例输入
1 1
5 7 5 13
10
样例输出
55

第二题描述

小h拥有n位朋友。每位朋友拥有ai和bi两个数值表示魅力值和萌力值。

现在小h要和其中k位朋友一起聚餐。根据他和小y的交易,他会先筛选出p位朋友,然后交给小y来筛选出其中的k位朋友。

假设小h已经选取了确定的p位朋友,小y筛选朋友的标准是使没有被筛选到的p-k个朋友的萌力值bi之和最小;如果有多个最小化萌力值之和的方案,再最小化被选到的朋友的魅力值ai的和。

但是小h不希望这样,他希望选出p个朋友后使得小y选出的最终的k个朋友魅力值ai之和最大化(在所有p个朋友的选择方案中),在此基础上最大化没有被选到的p-k的妹子的萌力值bi之和

你能告诉他应该选择哪p个朋友可以达到他的目的吗。

你只需要输出选出的p个朋友的魅力值ai和萌力值bi之和。

输入

第一行3个整数,n,p,k;

接下来n行,每行2个整数,ai,bi

1<=k<=p<=n<=3*105

ai,bi<=n

输出

共一行2个整数,suma,sumb,分别表示选出的p个朋友的ai,bi之和。

样例解释

如果小h选择了(2,1)和(3,4),那么小y会选择(3,4),被小y选上的魅力值和为3,被小h选上而未被小y选上的萌力值和为1。

如果小h选择了(2,1)和(5,2),那么小y会选择(5,2),被小y选上的魅力值和为5,被小h选上而未被小y选上的萌力值和为1。

如果小h选择了(3,4)和(5,2),那么小y会选择(3,4),被小y选上的魅力值和为3,被小h选上而未被小y选上的萌力值和为2。

所以小h应选择(2,1)和(5,2)。

样例输入
3 2 1
2 1
3 4
5 2
样例输出
7 3

第三题描述

小h拥有n位朋友。每位朋友拥有一个数值Vi代表他与小h的亲密度。亲密度有可能发生变化。

岁月流逝,小h的朋友们形成了一种稳定的树状关系。每位朋友恰好对应树上的一个节点。

每次小h想请两位朋友一起聚餐,他都必须把连接两位朋友的路径上的所有朋友都一起邀请上。并且聚餐的花费是这条路径上所有朋友的亲密度乘积。

小h很苦恼,他需要知道每一次聚餐的花销。小h问小y,小y当然会了,他想考考你。

输入

输入文件第一行是一个整数n,表示朋友的数目,从1开始编号。

输入文件第二行是n个正整数Vi,表示每位朋友的初始的亲密度。

接下来n-1行,每行两个整数u和v,表示u和v有一条边。

然后是一个整数m,代表操作的数目。每次操作为两者之一:

0 u v 询问邀请朋友u和v聚餐的花费

1 u v 改变朋友u的亲密度为v

1<=n,m<=5*105

Vi<=109

输出

对于每一次询问操作,你需要输出一个整数,表示聚餐所需的花费。你的答案应该模1,000,000,007输出。

样例输入
3
1 2 3
1 2
2 3
5
0 1 2
0 1 3
1 2 3
1 3 5
0 1 3
样例输出
2
6
15

第四题描述

小h喜欢妹子,然而妹子喜欢兔子,于是小h在家中养了3只兔子。

有一天,兔子不堪寂寞玩起了游戏。3只兔子排成一排,分别站在数轴上a,b,c这3个位置。游戏的规则是这样的,重复以下步骤若干次:选择两个不同的兔子A和B,假如它们位于X与Y,A可以从X跳到Y+Y-X处,但是跳跃时是不允许一下子跳过两只兔子的,也就是说第三只兔子不能在区间[min{X,Y+Y-X},max{X,Y+Y-X}]的范围内。现在小h十分伤心,因为妹子问他兔子怎么跳的,然而他并不知道。

我们称三只兔子的位置组成的三元组(a,b,c) a<b<c为一种状态S。

初始时三只兔子在a0,b0,c0的位置,c0-b0=b0-a0 且 a0<b0<c0。设初始状态为S0,则对于任意状态S,如果存在一个最短的跳跃序列使得从S0经过k次跳跃后能达到状态S,我们定义f(S)=k。

我们称一个状态集合为兔子从S0出发,经过若干步跳跃后所有跳到的状态构成的集合。两个状态集合A和B不同,当且仅当存在状态S使得S在A中不在B中或者相反。

小h想知道,兔子可以到达多少种不同的状态集合A,满足以下两个条件:

1: |A|=n。

2: Max(f(S),S∈A)=k。

输出最终答案模998244353的答案。

输入

第一行1个整数T,表示数据组数;

接下来T行,每行5个整数,a, b, c, n,k

1<=n<=1200, 1<=k<=1200, 1<=T<=1000000, -50000<a<b<c<50000。

输出

每组数据输出一行,一个整数,表示最终答案。

样例解释

对于第一个样例,可能的两种状态集合应当是{(0,1,2),(-1,0,2)}和{(0,1,2),(0,2,3)}。

样例输入
2
0 1 2 2 1
128 256 384 3 2
样例输出
2
4

参考程序

第一题:

#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <cassert>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
// head

typedef vector<ll> VL;
typedef vector<VL> matrix;
matrix mul(const matrix &a,const matrix &b) {
	int n=SZ(a);
	matrix c(n,VL(n,0));
	rep(i,0,n) rep(j,0,n) rep(k,0,n) c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mod;
	return c;
}
void multo(matrix &a,const matrix &b) {
	int n=SZ(a);
	matrix c(n,VL(n,0));
	rep(i,0,n) rep(j,0,n) rep(k,0,n) c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mod;
	rep(i,0,n) rep(j,0,n) a[i][j]=c[i][j];
}
matrix add(const matrix &a,const matrix &b) {
	int n=SZ(a);
	matrix c(n,VL(n,0));
	rep(i,0,n) rep(j,0,n) {
		c[i][j]=a[i][j]+b[i][j];
		if (c[i][j]>=mod) c[i][j]-=mod;
	}
	return c;
}
void addto(matrix &a,const matrix &b) {
	int n=SZ(a);
	rep(i,0,n) rep(j,0,n) { a[i][j]+=b[i][j]; if (a[i][j]>=mod) a[i][j]-=mod;}
}
matrix unit(int n,int w=1) {
	matrix c(n,VL(n,0));
	rep(i,0,n) c[i][i]=w;
	return c; 
}
matrix powmod(matrix a,ll b) {
	int n=SZ(a);
	matrix res=unit(n);
	for (;b;b>>=1) { if(b&1) multo(res,a);multo(a,a);}
	return res;
}
matrix powsmod(matrix a,ll b) {
	int n=SZ(a);
	matrix res=unit(n),_a=a;
	int k=0;for (;b>>k;k++);--k;
	while(--k>=0) {
		addto(a,unit(n));multo(res,a);
		addto(a,unit(n,-1));multo(a,a);
		if ((b>>k)&1) multo(res,_a),addto(res,unit(n)),multo(a,_a);
	}
	return res;
}

int k1,k2,ax,ay;
matrix base,g1,g2,g3;
ll a1,a2,x,y,z;
void solve(ll a,ll b,ll c,ll d,ll e,ll f) {
	// ax+by=c
	// dx+ey=f
//	printf("%lld %lld %lld %lld %lld %lld\n",a,b,c,d,e,f);
	if ((a*e-b*d)%mod==0) {
		if (a==0&&b==0) swap(a,d),swap(b,e),swap(c,f);
		if (b!=0) {
			// b!=0
			a1=0; a2=c*powmod(b,mod-2)%mod;
		} else {
			a1=c*powmod(a,mod-2)%mod; a2=0;
		}
	} else {
		a1=(c*e-f*b)%mod*powmod(a*e-b*d,mod-2)%mod;
		a2=(f*a-c*d)%mod*powmod(a*e-b*d,mod-2)%mod;
		if (a1<0) a1+=mod;
		if (a2<0) a2+=mod;
	}
}
int main() {
	scanf("%d%d",&k1,&k2);
	scanf("%lld%lld%d%d",&x,&y,&ax,&ay);
	base=unit(2,0);
	base[0][1]=1;
	base[1][0]=k2;
	base[1][1]=k1;
	g1=powmod(base,x-2);
	g2=powmod(base,y-2);
	solve(g1[1][0],g1[1][1],ax,g2[1][0],g2[1][1],ay);
	scanf("%lld",&z);
	g3=powmod(base,z-2);
	printf("%lld\n",(g3[1][0]*a1+g3[1][1]*a2)%mod);
}


第二题:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;

struct on {
    LL a, b;
    int id;
    bool operator < (const on &A) const {
        return b != A.b ? b > A.b : a < A.a;
    }
}no[300010];

bool cmp (on A, on B) {
    return A.a != B.a ? A.a > B.a : A.b > B.b;
}

int main () {
    int n, p, k;
    while (~scanf ("%d%d%d", &n, &p, &k)) {
        for (int i = 1; i <= n; i++) {
            scanf ("%lld%lld", &no[i].a, &no[i].b);
        }
        sort (no + 1, no + n + 1);
        for (int i = 1; i <= n; i++)    no[i].id = i;
        int num = (n - (p - k));
        LL ans1 = 0, ans2 = 0;
        sort (no + 1, no + num + 1, cmp);
        int ct = 0;
        for (int i = 1; i <= k; i++) {
            ans1 += no[i].a, ans2 += no[i].b;
            ct = max (ct, no[i].id);
        }
        sort (no + 1, no + n + 1);
        int pk = p - k;
        for (int i = ct + 1, j = 1; j <= pk; i++, j++) {
            ans1 += no[i].a, ans2 += no[i].b;
        }
        printf ("%lld %lld\n", ans1, ans2);
    }
    return 0;
}


第三题:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <cassert>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
// head

const int N=501000;
int q[N],hs[N],hv[N],dep[N],id[N],l[N],r[N],bel[N],s[N],f[N],val[N];
int n,m,Q,tot,u,v,k,ty;
VI e[N],vec[N],ret;
ll z;
struct node {
	ll s;
}nd[4*N];
void upd(int p) {
	nd[p].s=nd[p+p].s*nd[p+p+1].s%mod;
}
void build(int p,int l,int r) {
	if (l==r) {
		nd[p].s=val[id[l]];
	} else {
		int md=(l+r)>>1;
		build(p+p,l,md);
		build(p+p+1,md+1,r);
		upd(p);
	}
}
ll query(int p,int l,int r,int tl,int tr) {
	if (tl==l&&tr==r) return nd[p].s;
	else {
		int md=(l+r)>>1;
		if (tr<=md) return query(p+p,l,md,tl,tr);
		else if (tl>md) return query(p+p+1,md+1,r,tl,tr);
		else return query(p+p,l,md,tl,md)*query(p+p+1,md+1,r,md+1,tr)%mod;
	}
}
void modify(int p,int l,int r,int x,ll v) {
	if (l==r) nd[p].s=v;
	else {
		int md=(l+r)>>1;
		if (x<=md) modify(p+p,l,md,x,v);
		if (x>md) modify(p+p+1,md+1,r,x,v);
		upd(p);
	}
}

void dfs(int u,int f) {
	id[l[u]=++tot]=u;
	dep[u]=dep[f]+1;
	if (hv[u]) dfs(hv[u],u);
	rep(j,0,SZ(e[u])) if (e[u][j]!=f&&e[u][j]!=hv[u])
		dfs(e[u][j],u);
	r[u]=tot;
}
void HLDoT(int rt) {
	int t=1;
	q[0]=rt;
	rep(i,0,n) {
		int u=q[i];
		rep(j,0,SZ(e[u])) if (e[u][j]!=f[u])
			f[e[u][j]]=u,dep[q[t++]=e[u][j]]=dep[u]+1;
	}
	per(i,0,n) {
		int u=q[i],p=f[u];
		s[u]++,s[p]+=s[u];
		if (!l[u]) l[u]=1;
		if (hs[p]<s[u]) hs[p]=s[u],hv[p]=u,l[p]=l[u]+1;
	}
	rep(i,0,n) {
		int u=q[i];
		if (!bel[u]) bel[u]=u;
		if (hv[u]) bel[hv[u]]=bel[u];
	}
	dfs(rt,0);
}
void query(int u,int v) {
	while (1) {
		if (bel[u]==bel[v]) {
			if (dep[u]<dep[v]) swap(u,v);
			z=z*query(1,1,n,l[v],l[u])%mod;
			break;
		} else {
			if (dep[bel[u]]<dep[bel[v]]) swap(u,v);
			z=z*query(1,1,n,l[bel[u]],l[u])%mod;
			u=f[bel[u]];
		}
	}
}

int main() {
	scanf("%d",&n);
	rep(i,1,n+1) scanf("%d",val+i);
	rep(i,1,n) {
		scanf("%d%d",&u,&v);
		e[u].pb(v); e[v].pb(u);
	}
	HLDoT(1);
	build(1,1,n);
	scanf("%d",&Q);
	rep(i,0,Q) {
		scanf("%d",&ty);
		if (ty==0) {
			scanf("%d%d",&u,&v);
			z=1;
			query(u,v);
			printf("%lld\n",z);
		} else {
			scanf("%d%d",&u,&v);
			modify(1,1,n,l[u],v);
		}
	}
}

第四题:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <cassert>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=998244353;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
// head

int dp[1300][1300];
int n=4096,ta[5010],k,_;
ll w[10010],ww[10010],t[10010];
void dft(int *a,ll *w,int st,int len,int n) {
	if (n==1) return; n>>=1;
	dft(a,w,st,len+1,n);
	dft(a,w,st+(1<<len),len+1,n);
	rep(i,0,n) {
		int p=st+(i<<(len+1));
		ll wt=(w[i<<len]*a[p+(1<<len)])%mod;
		t[i]=a[p]+wt; if (t[i]>=mod) t[i]-=mod;
		t[i+n]=a[p]-wt; if (t[i+n]<0) t[i+n]+=mod;
	}
	rep(i,0,2*n) a[st+(i<<len)]=t[i];
}

int main() {
	ll t=powmod(3,(mod-1)/n);
	w[0]=1; rep(i,1,n) w[i]=(w[i-1]*t)%mod;
	ww[0]=1; rep(i,1,n) ww[i]=powmod(w[i],mod-2);
	ll invn=powmod(n,mod-2);
	dp[0][0]=1; dp[0][1]=1;
	rep(i,1,1201) {
		rep(j,0,1201) ta[j]=dp[i-1][j];
		rep(j,1201,n) ta[j]=0;
		dft(ta,w,0,0,n);
		rep(j,0,n) ta[j]=(ll)ta[j]*ta[j]%mod;
		dft(ta,ww,0,0,n);
		rep(j,0,n) ta[j]=ta[j]*invn%mod;
		rep(j,1,1201) dp[i][j]=ta[j-1];
		dp[i][0]=1;
	}
	for (scanf("%d",&_);_;_--) {
		scanf("%*d%*d%*d%d%d",&n,&k);
		int ret=dp[k][n]-dp[k-1][n];
		if (ret<0) ret+=mod;
		printf("%d\n",ret);
	}
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值