2020.10.16 【NOIP2014】普及組模擬賽總結

Jackma_mayichao發表於2020-10-16
編號題目
T1小 X 的加法難題
T2小 X 的密碼破譯
T3小 X 的液體混合
T4小 X 的 AK 計劃

T1

有道理!

思路

直接模擬
注意 L a r g e Large Large 的判斷:

  1. 第一個數或第二個數超過 1 0 8 10^8 108
  2. 超過 1 0 8 10^8 108

程式碼

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long a,b,c,tj,w;
string s;
int input()
{
	int dep=0;
	while(s[dep]!='+')   //讀入+號前面的部分
	 {
	 	if('0'<=s[dep]&&s[dep]<='9')
	 	  a=a*10+s[dep]-48,tj++;
	 	if(tj>9)
	 	 {
	       cout<<"Large";
	       w=1;
	 	   return 0;
		 }
	 	dep++;
	 }
	if(a>100000000)
	 {
	    cout<<"Large";
	    w=1;
	 	return 0;
	 }
	dep++,tj=0;
	while(dep<=s.size())  //讀入+號後面的部分
	 {
	 	if('0'<=s[dep]&&s[dep]<='9')
	 	  b=b*10+s[dep]-48,tj++;
	 	if(tj>9)
	 	 {
	       cout<<"Large";
	       w=1;
	 	   return 0;
		 }
	 	dep++;
	 }
	if(b>100000000)
	 {
	    cout<<"Large";
	    w=1;
	 	return 0;
	 }
	return a+b;
}
int main()
{
	freopen("sum.in","r",stdin);
	freopen("sum.out","w",stdout);
	getline(cin,s);
	c=input();
	if(w==1)
	  return 0;
	if(c>100000000)
	  cout<<"Large";
	else
	  cout<<c;
	return 0;
}

T2

在這裡插入圖片描述

思路

直接模擬
注意點:

  1. 要開 l o n g   l o n g long~long long long;
  2. 陣列要開 b o o l bool bool 型別;
  3. 算密碼從 0 0 0 開始算:當 a = 0 , b = 0 , c = 0 a=0,b=0,c=0 a=0,b=0,c=0 d d di = 0 =0 =0 e e e 陣列會存到 0 0 0 號下標。

程式碼

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int P=11111111;
long long n,a,b,c,ans,js=1;
long long d[P+1];
bool e[P+1];
int main()
{
	freopen("password.in","r",stdin);
	freopen("password.out","w",stdout);
	scanf("%lld %lld %lld %lld",&n,&a,&b,&c);
	for(int i=1; i<=n; i++)
	 {
	   d[i]=(a*i*i%P+b*i%P+c)%P;
	   e[d[i]]=1;
	 }
	for(int i=0; i<=P; i++)
	 if(e[i]!=0)
	   ans=(ans+js*i)%P,js++;
	cout<<ans;
	return 0;
}

T3

在這裡插入圖片描述

思路

對於一個連通塊,
我們加入的第一種液體一定不會使危險係數乘 2
之後我們從這種液體出發dfs,
只要按遍歷順序加入其他液體,
每次加入都能使危險係數乘 2
注意計算答案時要用到高精度乘法

程式碼

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long n,m,x,y,js,wss=1;
long long gjc[101000],h[100100],c[100100];
long long tot;
struct node
{
	long long y,next;
}a[100100];
void add(long long x,long long y)
{
	a[++tot].y=y;
	a[tot].next=h[x];
	h[x]=tot;
}
void jgjc()
{
	int tj=0;
	for(long long i=1; i<=wss; i++)
	 {
	 	gjc[i]=gjc[i]*2+tj;
	 	tj=gjc[i]/10;
	 	gjc[i]%=10;
	 }
	if(tj!=0)
	  gjc[++wss]=tj;
}
void dfs(long long x)
{
	c[x]=1;
	for(long long i=h[x]; i; i=a[i].next)
	 {
	 	long long y=a[i].y;
	 	if(c[y]==0)
	 	 {
	 	 	dfs(y);
	 	 	jgjc();
		 }
	 }
}
int main()
{
	freopen("mixture.in","r",stdin);
	freopen("mixture.out","w",stdout);
	cin>>n>>m;
	for(int i=1; i<=m; i++)
	 {
	 	scanf("%lld%lld",&x,&y);
	 	add(x,y);
	 	add(y,x);
	 }
	gjc[1]=1;
    for(int i=1; i<=n; i++)
     if(c[i]==0)  //沒跑過的才跑
       dfs(i);
    for(int i=wss; i>=1; i--)
       printf("%lld",gjc[i]);
	return 0;
}

T4

在這裡插入圖片描述

思路

首先按照當前地點到家的距離排序。
並建立一個大根用來維護 1 1 1 ~ i − 1 i-1 i1 的AK所需時間。
然後遍歷排好序的資料,要是這個房間能 AK ,那就加上AK時間
要是這個機房時間不夠了,就從 1 1 1 ~ i − 1 i-1 i1 那裡找一個時間最大的AK
把時間拿回來給這個機房AK。在這個過程中,要不斷取 max ⁡ \max max
在決策過程中,要是出現就算怎麼反還時間也不夠的話,說明後面的所有機房都AK不了,
所以直接結束迴圈即可。

程式碼

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define pi pair<long long,long long>
#define ai make_pair
using namespace std;
priority_queue<pi>q;
long long n,m,now_t,js,ans;
struct node
{
	long long x,t;
}a[1000010];
bool cmp(const node&a,const node&b)
{
	return a.x<b.x;
}
int main()
{
	freopen("plan.in","r",stdin);
	freopen("plan.out","w",stdout);
	cin>>n>>m;
	for(int i=1; i<=n; i++)
       scanf("%lld%lld",&a[i].x,&a[i].t);
	sort(a+1,a+1+n,cmp);
	for(int i=1; i<=n; i++)
	 {
	 	now_t+=a[i].x-a[i-1].x;    //距離所需時間
	 	js++;   //AK機房++
	 	q.push(ai(a[i].x,a[i].t));
	 	now_t+=a[i].t;
	 	while(now_t>m&&q.size()!=0)   //返還時間(大根堆堆頭是最大的)
	 	 {
	 	 	js--;
	 	    now_t-=q.top().second;
	 	    q.pop();
		 }
		if(now_t>m)
		  break;
		ans=max(ans,js);
	 }
	cout<<ans;
	return 0;
}

相關文章