1. 程式人生 > >2018.9.23考試總結

2018.9.23考試總結

三道思維題,分享一下 第一題

melon 【時間限制】1000MS 【空間限制】65536KB 【輸入檔案】melon. in 【輸出檔案】melon.out 【題目描述】 Todobe和Yahsem66比賽吃瓜。 桌上一共有n塊瓜,他們可以從桌上拿走不多於k塊瓜來吃,吃一塊瓜需要1分鐘的時間,只有吃完手裡的所有瓜之後才可以再去拿瓜,拿瓜的時間不計。如果兩人在同一時間點拿瓜,Yashem66會發揚謙讓精神讓Todobe先拿,開始比賽時也是Todobe先拿。 舉個例子,如果n=10,k=4,Todobe先拿走3塊,Yashem66拿走2塊,Yashem66吃完之後Todobe還有1塊沒有吃完。Yashem66再拿走4塊,然後Todobe就只能再吃到1塊,最終Todobe吃了4塊,而Yashem66吃了6塊。 兩個人都想盡可能吃更多的瓜,貪吃的Todobe想知道她最多能吃到多少塊瓜。 【輸入】 輸入包括一行兩個整數,n、k。 【輸出】 輸出一行一個整數,代表Todobe最多能吃到多少塊瓜。 【樣例輸入1】 2 1 【樣例輸出1】 1 【樣例輸入2】 10 4 【樣例輸出2】 5 【資料範圍與約定】 對於0%的資料,與樣例相同; 對於10%的資料,n<=2*k; 對於另30%的資料,k=2; 對於100%的資料,n,k<=100000。

這道題就是考慮情況周全,n<=k直接是n,k<n<=2k就是k 當n>2k時,考慮一次只吃一個瓜,這樣就有更大決策空間 當剩餘瓜數<=2*k時直接選k個 所以答案為ceil(n/2) Code

#include<cstdio>
#include<iostream>
using namespace std;
int n,k;
int main()
{
	freopen("melon.in","r",stdin);
	freopen("melon.out","w",stdout);
	scanf("%d%d",&n,&k);
	if
(n<=k) { printf("%d",n); } else if(n<=2*k) { printf("%d",k); } else printf("%d",(n+1)/2); return 0; }

第二題

change 【時間限制】2000MS 【空間限制】524288KB 【輸入檔案】change.in 【輸出檔案】change.out 【題目描述】 Todobe開了一家店,Yashem66連續n天都會光顧這家店。 Yashem66只有100元的紙幣和1元的硬幣,他知道Todobe懶的一批,很討厭找零這件事情,每天Todobe都會有一個心情值wi,如果Todobe第i天需要找零,那她的不愉悅度就會增加wi*找零的錢數。當Todobe需要找零時,她也會找給Yashem66若干1元硬幣,但她不會找給Yashem66 100個及以上的硬幣。 假設Yashem66一開始有足夠的紙幣和m個硬幣,他在第i天,會買價值ci元的產品。他想盡可能降低Todobe的不愉悅度,請你告訴他Todobe 的不愉悅度最少是多少。 【輸入】 第一行兩個整數n、m。 第二行有n個整數,第i個整數代表ci,第i天Yashem66購買的價格。 第三行有n個整數,第i個整數代表wi,第i天Todobe的心情值。 【輸出】 輸出一行一個整數代表Todobe不愉悅度的最小值。 【樣例輸入1】 5 42 117 71 150 243 200 1 1 1 1 1 【樣例輸出1】 79 【樣例解釋1】 第一天花費1張100元紙幣和17個1元硬幣,剩餘25個硬幣,不愉悅度為0; 第二天花費1張100元紙幣,找零29,剩餘54個硬幣,不愉悅度為29; 第三天花費2張100元紙幣,找零50,剩餘104個硬幣,不愉悅度為79; 第四天花費2張100元紙幣和43個1元硬幣,剩餘61個硬幣,不愉悅度為79; 第五天花費2張100元紙幣,不愉悅度為79. 【樣例輸入2】 5 42 117 71 150 243 200 5 4 3 2 1 【樣例輸出2】 230 【樣例解釋2】 第一天花費1張100元紙幣和17個1元硬幣,剩餘25個硬幣,不愉悅度為0; 第二天花費1張100元紙幣,找零29,剩餘54個硬幣,不愉悅度為116; 第三天花費1張100元紙幣和50個1元硬幣,剩餘4個硬幣,不愉悅度為116; 第四天花費3張100元紙幣,找零57,剩餘61個硬幣,不愉悅度為230; 第五天花費2張100元紙幣,不愉悅度為230. 【資料範圍與約定】 對於0%的資料與樣例相同; 對於20%的資料,n<=20; 對於另20%的資料,ci=1; 對於100%的資料,n<=105,m<=10

9,1<=ai,ci<=10^5。

首先一個優化,就是0<=c[i]<100,先%100 這道題考慮貪心,就是隻要能買就買,如果錢不夠了怎麼辦? 考慮之前買的,因為已經付了c[i],而找零是100-c[i],加一起就是你花100-c[i]的不愉悅度,得到100元,用堆維護每次取最小即可 Code

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
struct poi
{
	int id,num;
	bool operator < (const poi &a)const
	{
		return num>a.num;
	}
};
int n,m;
int c[100005];
int w[100005];
long long ans;
priority_queue<poi> q;
int ans2[100005];
int minn=1000000000;
int anss[100005];
void dfs(int x,int lst,int un)
{
	if(lst<=anss[x]&&un>=ans2[x])return ;
	if(lst>=anss[x]&&un<=ans2[x])
	{
		anss[x]=lst;
		ans2[x]=un;
	}
	if(x==n)
	{
		minn=min(minn,un);
		return ;
	}
	if(lst>=c[x+1])dfs(x+1,lst-c[x+1],un);
	dfs(x+1,lst+100-c[x+1],un+w[x+1]*(100-c[x+1]));
}
int main()
{
	freopen("change.in","r",stdin);
	freopen("change.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&c[i]);
		c[i]%=100;
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&w[i]);
	}
	if(n<=20)
	{
	dfs(0,m,0);
	printf("%d",minn);	
	return 0;
	}
	for(int i=1;i<=n;i++)
	{
		if(!(c[i]%100))continue;
		poi x;
		x.id=i;
		x.num=w[i]*(100-c[i]);
		q.push(x);
		m-=c[i];
		if(m<0)
		{
			poi cc=q.top();
			q.pop();
			ans+=cc.num;
			m+=100;
		}
	}
	printf("%lld",ans);
}

第三題 :我出這道題就不是讓你們做的。。。 好吧,我連矩乘都不會

paint 【時間限制】1000MS 【空間限制】524288KB 【輸入檔案】paint.in 【輸出檔案】paint.out 【題目描述】 Todobe要把她的寢室弄得漂漂釀釀,所以她管Yashem66要了一些牆紙。 Todobe有一面牆,可分為n塊,Yashem66提供的所有牆紙都是統一規格的,均只可覆蓋連續k塊完整的牆面,但是有m種不同的顏色的牆紙,每種顏色的牆紙都有無限張。Todobe要用這些牆紙把牆貼滿,牆紙不可以裁剪,牆紙與牆紙之間可以有重疊部分。當牆紙重疊時,只能看到最外層的牆紙顏色。 Todobe想知道她以不同的方式貼牆紙,共能貼出多少種不同配色方案的牆面,兩種方案不同當且僅當兩種方案中至少有一塊牆面的顏色不同。 【輸入】 輸入一行3個整數n,m,k。 【輸出】 輸出一行一個整數代表方案數量,答案取模1e9+7。 【樣例輸入1】 3 2 2 【樣例輸出1】 6 【樣例輸入2】 10 4 3 【樣例輸出2】 371740 【樣例解釋】 對於樣例輸入1,我們假設兩種顏色分別是A,B 那麼6種方案分別是:AAA,AAB,ABB,BAA,BBA,BBB 【資料範圍與約定】 對於0%的資料,與樣例資料相同; 對於20%的資料,n<=10,m<=5; 對於另20%的資料n<=500; 對於另20%的資料n<=10^5; 對於100%的資料n<=231-1,m<=10^5,k<=100。

這道題可以先求出不合法方案數,再用nm減一下就好了 原題變成求m種顏色若干段區間,每段都小於k f[i]=(f[i-1]+f[i-2]+……+f[i-k+1])*(m-1) 矩乘優化就好了 不會戳這裡 Code

#include<bits/stdc++.h>
using namespace std;
int n,m,K;
const int mod=1000000007;
struct mat
{
	long long a[105][105];
	mat operator *(const mat &x)const
	{
		mat f;
		for(int i=0;i<K;i++)
		for(int j=0;j<K;j++)
		{
			f.a[i][j]=0ll;
			for(int k=0;k<K;k++)
			f.a[i][j]=(f.a[i][j]+a[i][k]*x.a[k][j])%mod;
		}
		return f;
	}
}A,T;
long long ksm(int x,int y)
{
	long long re=1;
	long long pl=x;
	while(y)
	{
		if(y&1)re=re*pl%mod;
		pl=pl*pl%mod;
		y>>=1;
	}
	return re;
}
void ksm(mat x,int y)
{
	while(y)
	{
		if(y&1)
		{
			A=A*x;
		}
		x=x*x;
		y>>=1;
	}
	return ;
}
long long ans;
int main()
{
	freopen("paint.in","r",stdin);
    freopen("paint.out","w",stdout);
	scanf("%d%d%d",&n,&m,&K);
	ans=ksm(m,n);
	K--;
	A.a[0][0]=m;
	for(int i=1;i<K;i++)
	A.a[0][i]=A.a[0][i-1]*m%mod;
	for(int i=0;i<K-1;i++)
	{
	T.a[i+1][i]=1;	
	}
	for(int i=0;i<K;i++)
	T.a[i][K-1]=m-1;
	ksm(T,n-K);
	ans=((ans-A.a[0][K-1])%mod+mod)%mod;
	printf("%lld",ans);
	return 0;
}