gym103447

A.So Many Lucky Strings

B.Magical Subsequence

        注意到a[i]很小,所以和很小,枚举和的具体值,dp一下即可

      

#include<bits/stdc++.h>
#define N 500005

using namespace std;

int n,a[N],f[N],b[N],lst[N];

int main(){
	scanf("%d",&n);int ans=0;
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	for (int i=2;i<=200;i++){
		for (int j=1;j<=200;j++) b[j]=0;
		for (int j=1;j<=n;j++){
			if (i-a[j]>0) lst[j]=b[i-a[j]];
			b[a[j]]=j;
			f[j]=0;
		}
		f[0]=0;
		for (int j=2;j<=n;j++){
			f[j]=f[j-1];
			if (!lst[j]) continue;
			f[j]=max(f[j],f[lst[j]-1]+1);
		}
		ans=max(ans,f[n]);
	}
	printf("%d\n",ans*2);
	return 0;
}

C.Colorful Tree

D.Math master

        注意到位数很小,最多只有19位,因此暴力枚举分子删掉了哪些位数,判断一下分母是否可以同样做到即可

#include<bits/stdc++.h>
#define int long long
#define N 1000005

using namespace std;

const int mod=1e9+7;
const int bas=233333;
set<int>S[N];
map<int,int>mp;
int T,n,m,tot,a[N],b[N],c[N],bin[N];

signed main(){
	scanf("%lld",&T);
	bin[0]=1;
	for (int i=1;i<=18;i++) bin[i]=bin[i-1]*10;
	while (T--){
		for (int i=1;i<=tot;i++) S[i].clear();
		mp.clear();tot=0;
		int cnt1=18,cnt2=18;
		scanf("%lld%lld",&n,&m);
		for (int i=0;i<=18;i++){
			int tmp=n/bin[i];
			if (tmp==0){cnt1=i-1;break;}
			a[i]=tmp%10;
		}
		for (int i=0;i<=18;i++){
			int tmp=m/bin[i];
			if (tmp==0){cnt2=i-1;break;}
			b[i]=tmp%10;
		}
		for (int i=1;i<(1<<(cnt1+1))-1;i++){
			int now=0;
			for (int j=cnt1;~j;j--)
				if (!(i>>j&1)) now=now*10ll+a[j];
			if (!now) continue;
			for (int j=0;j<=cnt1;j++)
				if (i>>j&1) c[a[j]]++;
			int sum=0;
			for (int j=0;j<10;j++)
				sum=(sum*bas%mod+(c[j]+1))%mod;
			for (int j=0;j<=cnt1;j++)
				if (i>>j&1) c[a[j]]--;
			if (!mp[sum]) mp[sum]=++tot;
			S[mp[sum]].insert(now);
		}
		int ansx=n,ansy=m;
		for (int i=1;i<(1<<(cnt2+1))-1;i++){
			int now=0;
			for (int j=cnt2;~j;j--)
				if (!(i>>j&1)) now=now*10ll+b[j];
			if (!now) continue;
			for (int j=0;j<=cnt2;j++)
				if (i>>j&1) c[b[j]]++;
			int sum=0;
			for (int j=0;j<10;j++)
				sum=(sum*bas%mod+(c[j]+1))%mod;
			for (int j=0;j<=cnt2;j++)
				if (i>>j&1) c[b[j]]--;
			if (!mp[sum]) continue;
			__int128 tmp=(__int128)n*now;
			if (tmp%m) continue;
			int tmp1=tmp/m;
			if (S[mp[sum]].find(tmp1)!=S[mp[sum]].end())
				if (tmp1<ansx) ansx=tmp1,ansy=now;
		}
		printf("%lld %lld\n",ansx,ansy);
	}
	return 0;
}

 E.Power and Modulo

找到第一个不是2^i的变值,即可算出M的值,再O(n)检验一遍即可

#include<bits/stdc++.h>
#define N 200005

using namespace std;

int n,a[N];

inline int ksm(int x,int y,int mod){
	int ans1=1;while (y){
		if (y&1) ans1=1ll*ans1*x%mod;
		y>>=1;x=1ll*x*x%mod;
	}return ans1;
}

int main(){
	int T;scanf("%d",&T);
	while (T--){
		scanf("%d",&n);
		int M=0;
		for (int i=1;i<=n;i++) scanf("%d",&a[i]);
		for (int i=1;i<=n;i++){
			if (a[i]==(1<<(i-1))) continue;
			M=(1<<(i-1))-a[i];
			break;
		}
		if (!M){
			puts("-1");
			continue;
		}
		for (int i=1;i<=n;i++)
			if (ksm(2,i-1,M)%M==a[i]) continue;
			else{M=-1;break;}
		printf("%d\n",M);
	}
	return 0;
} 

F.Master Spark 

G.Damaged Bicycle

期望dp

发现k很小,考虑状压,正着做很难设计状态,也不好转移,考虑倒着

用dps,i表示经过了s集合的点,现在在i,到n的最小期望(此时有没有骑上车不确定)

考虑转移dps,i由dp[s∪{j}][j]转移而来,转移方程讨论j这个点是否骑到车子

即dp[s][i]=min(dp[s][i],(dp[s∪{j}][j]+1.0*dis[i][j]/t)*p[i]+(1.0*dis[i][n]/r)*(1-p[i]));

#include<bits/stdc++.h>
#define int long long
#define mk make_pair
#define N 500005

using namespace std;

long double p[N],dp[N][19];
int n,m,cnt,a[N],fa[N],dis[19][N];
vector<pair<int,int> >g[N];
priority_queue<pair<int,int> >q;

int find(int x){if(x==fa[x])return x;return fa[x]=find(fa[x]);}

inline void dij(int x){
	for (int i=1;i<=n;i++) dis[x][i]=1e17;
	dis[x][a[x]]=0;
	q.push(mk(0,a[x]));
	while (q.size()){
		int u=q.top().second;
		q.pop();
		for (int i=0;i<(int)g[u].size();i++){
			int v=g[u][i].first;
			int w=g[u][i].second;
			if (dis[x][v]>dis[x][u]+w){
				dis[x][v]=dis[x][u]+w;
				q.push(mk(-dis[x][v],v));
			}
		}
	}
} 

signed main(){
	int t,r;scanf("%lld%lld",&t,&r);
	scanf("%lld%lld",&n,&m);
	for (int i=1;i<=n;i++) fa[i]=i;
	for (int i=1;i<=m;i++){
		int x,y,z;
		scanf("%lld%lld%lld",&x,&y,&z);
		g[x].push_back(mk(y,z));
		g[y].push_back(mk(x,z));
		fa[find(x)]=find(y);
	}
	if (find(1)!=find(n)) return puts("-1"),0;
	scanf("%lld",&cnt);
	for (int i=1;i<=cnt;i++) scanf("%lld%Lf",&a[i],&p[i]),p[i]=p[i]/100;
	a[0]=1;
	for (int i=0;i<=cnt;i++) dij(i);
	
	for (int i=(1<<cnt)-1;i;i--){
		for (int j=1;j<=cnt;j++){
			if (!(i>>(j-1)&1)) continue;
			dp[i][j]=1.0*dis[j][n]/t*p[j]+1.0*dis[j][n]/r*(1-p[j]);
			for (int k=1;k<=cnt;k++){
				if (i>>(k-1)&1) continue;
				dp[i][j]=min(dp[i][j],(dp[i|(1<<(k-1))][k]+1.0*dis[j][a[k]]/t)*p[j]+(1.0*dis[j][n]/r)*(1-p[j]));
			}
		}
	}
	long double ans=1.0*dis[0][n]/t;
	for (int j=1;j<=cnt;j++) ans=min(ans,1.0*dis[j][1]/t+dp[1<<(j-1)][j]);
	printf("%.10Lf\n",ans);
	return 0;
}

H.What logic for?

智力题

#include<bits/stdc++.h>
#define N 500005

using namespace std;

int n,m,k,t,a[N],b[N],c[N];

inline int lowbit(int x){return x&-x;}

inline void add(int x){for (int i=x;i<=t;i+=lowbit(i)) c[i]++;}

inline int sum(int x){
	int ans=0;
	for (int i=x;i;i-=lowbit(i)) ans+=c[i];
	return ans;
}

int check(vector<int>a,vector<int>b){
	multiset<int>A,B;
	t=a.size();
	for (int i=0;i<t;i++) A.insert(a[i]),B.insert(b[i]);
	if (A!=B) return -1;
	for (int i=0;i<t;i++) if (A.count(a[i])>1) return 2;
	map<int,int>pos;pos.clear();
	for (int i=0;i<t;i++) pos[b[i]]=i;
	memset(c+1,0,t*4);
	long long ans=0;
	for (int i=0;i<t;i++){
		a[i]=t-pos[a[i]];
		ans+=sum(a[i]);
		add(a[i]);
	}
	return ans&1;
}
int main(){
	int T;scanf("%d",&T);
	while (T--){
		scanf("%d",&n);
		for (int i=0;i<n;i++) scanf("%d",&a[i]);
		scanf("%d",&m);
		for (int i=0;i<m;i++) scanf("%d",&b[i]);
		scanf("%d",&k);
		if (n!=m){
			puts("NIE");
			continue;
		}
		int x=-1,fg=1;
		for (int t=0;t<k;t++){
			vector<int>a,b;
			a.clear();b.clear();
			for (int i=t;i<n;i+=k){
				a.emplace_back(::a[i]);
				b.emplace_back(::b[i]);
			}
			int y=check(a,b);
			if (y==-1){fg=0;break;}
			if (y<2){
				if (x==-1) x=y;
				else if (x!=y){fg=0;break;}
			}
		}
		if (fg) puts("TAK");
		else puts("NIE");
	}
	return 0;
}

I.Power and Zero

等价于一个长度位31的数组,每次能让一个前缀均-1,或者选中否个b[i],使得b[i]--,b[i+1]+=2

二分一个答案,等价于构造一个序列单减且均小于x,通过上述b的操作

#include<bits/stdc++.h>
#define int long long
#define N 500005

using namespace std;

int T,n,x,b[N],c[N];

inline bool check(int x){
	for (int i=0;i<31;i++) c[i]=b[i];
	for (int i=0;i<31;i++){
		if (c[i]>x) return 0;
		int tmp=(x-c[i])/2;
		c[i+1]-=tmp;
		x=min(x,c[i]+tmp*2);
	}
	return 1;
}

signed main(){
	scanf("%lld",&T);
	while (T--){
		scanf("%lld",&n);
		for (int i=0;i<31;i++) b[i]=0;
		for (int i=1;i<=n;i++){
			scanf("%lld",&x);
			for (int j=0;j<=30;j++)
				if (x>>j&1) b[j]++;
		}
		int l=b[0];int r=1e18;
		while (l+1<r){
			int mid=(l+r)>>1;
			if (check(mid)) r=mid;
			else l=mid;
		}
		if (check(l)) printf("%lld\n",l);else printf("%lld\n",r);
	}
	return 0;
}

J.Local Minimum 

#include<bits/stdc++.h>
#define N 2005

using namespace std;

int n,m,a[N][N],b[N],c[N];

int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++) scanf("%d",&a[i][j]);
	for (int i=1;i<=n;i++){
		b[i]=a[i][1];
		for (int j=2;j<=m;j++) b[i]=min(b[i],a[i][j]);
	}
	for (int i=1;i<=m;i++){
		c[i]=a[1][i];
		for (int j=2;j<=n;j++) c[i]=min(c[i],a[j][i]);
	}int ans=0;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			if (a[i][j]==c[j]&&a[i][j]==b[i]) ans++;
	printf("%d\n",ans);
	return 0;
} 

K.Wonder Egg Priority

L.Karshilov's Matching Problem

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值