1. 程式人生 > >2018提高組模擬13

2018提高組模擬13

20181027

T1 洛陽懷

【WOJ4150】

素數線性篩

GCD

數學推理

* _ *

多讀幾遍,不難發現:

  • 如果我們除以了前i個的GCD,那麼i以後的都不能除了
  • 每個數的分數是它的好的質因數個數減去壞的質因數個數(打表可以發現)

所以我們記錄一下每個數的好質因數的個數和壞質因數的個數,

再按記錄一個前i個數的GCD的好質因數的個數和壞質因數的個數。

因為我們除以後面對前面是沒有影響的,所以可以從後往前搜,

每次前i的GCD如果壞的多餘好的就除掉,再同步記錄一下lazy就好。

#include<iostream>
#include<cstdio>
#include<bitset>
#include<cctype>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x;
}
int t=0,pri[10000];
bitset<100010>c;
void find_prime(){
	for(int i=2;i<=100000;i++){
		if(!c[i])pri[++t]=i;
		for(int j=1;j<=t&&i*pri[j]<=100000;j++){
			c[i*pri[j]]=1;
			if(i%pri[j]==0)break;
		}
	}
}
int n,m,a[2010],b[2010],h;
int hao[2010],huai[2010],so[2010],si[2010];
bitset<1000000005>g;
void divide(int u){
	int x=a[u],j=1;
	while(pri[j]*pri[j]<=x){
		while(x%pri[j]==0){
			x/=pri[j];
			if(g[pri[j]])huai[u]++;
			else hao[u]++;
		}
		j++;
	}
	if(x>1){
		if(g[x])huai[u]++;
		else hao[u]++;
	}
}
int gcd(int x){
	int r;
	if(x>h){r=x;x=h;h=r;}
	while(x){
		r=x;
		x=h%x;
		h=r;
	}
	return h;
}
void divide_2(int x,int u){
	int j=1;
	while(pri[j]*pri[j]<=x){
		while(x%pri[j]==0){
			x/=pri[j];
			if(g[pri[j]])si[u]++;
			else so[u]++;
		}
		j++;
	}
	if(x>1){
		if(g[x])si[u]++;
		else so[u]++;
	}
}
int main(){
	n=read();m=read();
	find_prime();
	for(int i=1;i<=n;i++)
		a[i]=read();
	for(int i=1;i<=m;i++){
		b[i]=read();
		g[b[i]]=true;
	}
	h=a[1];divide(1);
	so[1]=hao[1];si[1]=huai[1];
	for(int i=2;i<=n;i++){
		divide(i);
		divide_2(gcd(a[i]),i);
	}
	int lazyo=0,lazyi=0,ans=0;
	for(int i=n;i>0;i--){
		so[i]-=lazyo;si[i]-=lazyi;
		if(si[i]>=so[i]){
			lazyo+=so[i];
			lazyi+=si[i];
		}
		hao[i]-=lazyo;huai[i]-=lazyi;
		ans+=(hao[i]-huai[i]);
	}
	printf("%d",ans);
	return 0;
}

T2 洗衣服

【WOJ2796】

貪心

* _ *

可以用堆。

我們給每一臺機器都安排一個任務。

然後每次取堆頂(最快做完的),再安排一個任務,入堆。

這樣取出最快的L個,加入一個數組。

洗衣機和烘乾機都一樣。

然後,根據排序不等式

在這裡插入圖片描述

兩臺機器,最大的配最小,再取一個MAX就是答案了 ^ _ ^

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x;
}
#define ll long long
int n,m,k,a[100010],b[100010];
ll l1[1000010],l2[1000010];
priority_queue< pair<ll,int> >q1;
priority_queue< pair<ll,int> >q2;
int main(){
	k=read();n=read();m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		q1.push(make_pair(-(ll)a[i],i));
	}
	for(int i=1;i<=m;i++){
		b[i]=read();
		q2.push(make_pair(-(ll)b[i],i));
	}
	for(int i=1;i<=k;i++){
		int y1=q1.top().second;
		ll x1=q1.top().first;q1.pop();
		l1[i]=-x1;q1.push(make_pair(x1-a[y1],y1));
		ll x2=q2.top().first;
		int y2=q2.top().second;q2.pop();
		l2[i]=-x2;q2.push(make_pair(x2-b[y2],y2));
	}
	ll ans=0;
	for(int i=1;i<=k;i++){
		ans=max(ans,l1[i]+l2[k-i+1]);
	}
	printf("%lld",ans);
	return 0;
}

T3 成績單

【WOJ3175】

區間DP

* _ *

題解:%%%LDX%%%

在這裡插入圖片描述
最後應該是 +f[j+1][t]

不難發現,g 的第一位都沒有變過,所以就強行壓下了一維。

看完後,打一打程式碼,大概就懂了……

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x;
}
int n,m,a,b;
int c[60],h[60];
int f[55][55],g[55][55][55];
int main(){
	n=read();a=read();b=read();
	for(int i=1;i<=n;i++){
		c[i]=h[i]=read();
		f[i][i]=a;
	}
	sort(h+1,h+n+1);
	int m=unique(h+1,h+n+1)-h-1;
	for(int i=1;i<=n;i++)
		c[i]=lower_bound(h+1,h+m+1,c[i])-h;
	for(int len=2;len<=n;len++)
		for(int l=1,r=len;r<=n;l++,r++){
			for(int i=l;i<=r;i++)
				for(int j=m;j;j--)
					for(int k=m;k>=j;k--)
						g[i][j][k]=1<<30;
			g[l][c[l]][c[l]]=0;
			for(int i=l;i<r;i++)
				for(int j=m;j>0;j--)
					for(int k=m;k>=j;k--){
						if(g[i][j][k]==1<<30)continue;
						int e=min(j,c[i+1]),d=max(k,c[i+1]);
						g[i+1][e][d]=min(g[i+1][e][d],g[i][j][k]);
						for(int t=r;t>i;t--)
							g[t][j][k]=min(g[t][j][k],g[i][j][k]+f[i+1][t]);
					}
			f[l][r]=1<<30;
			for(int j=m;j;j--)
				for(int k=m;k>=j;k--)
					f[l][r]=min(f[l][r],g[r][j][k]+a+b*(h[j]-h[k])*(h[j]-h[k]));
		}
	printf("%d",f[1][n]); 
	return 0;
}