diverta 2019 Programming Contest 2

  A:簽到。c++

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,m;
signed main()
{
	n=read(),m=read();
	if (m==1) cout<<0;else cout<<n-m;
	return 0;
	//NOTICE LONG LONG!!!!!
}

  B:若將全部差是(p,q)的點對鏈接起來,顯然會獲得若干條鏈,鏈的數量即爲答案。因而只要統計每種差的出現次數便可。優化

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 55
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
typedef pair<int,int> pii;
int n,ans;
struct data{int x,y;
}a[N];
map<pii,int> f;
signed main()
{
	n=read();
	for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
		if (i!=j)
		{
			ans=max(ans,++f[make_pair(a[i].x-a[j].x,a[i].y-a[j].y)]);
		}
	cout<<n-ans;
	return 0;
	//NOTICE LONG LONG!!!!!
}

  C:顯然應該儘可能加正數減負數。但同時容易發現至少有一個數要被減掉,至少有一個數要被加上,因此均爲正數或均爲負數時稍微修改一下。不妨設是排序後要將前p個數減掉,其餘數加上。那麼令a1依次減去ap+1~an-1,再令an依次減去a1~ap便可。spa

 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 100010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,a[N];
signed main()
{
	n=read();
	for (int i=1;i<=n;i++) a[i]=read();
	sort(a+1,a+n+1);
	int p=0;
	for (int i=1;i<=n;i++) if (a[i]<0) p=i;
	p=max(p,1);p=min(p,n-1);
	//讓前p個被減掉
	int s=0;
	for (int i=1;i<=p;i++)  s-=a[i];
	for (int i=p+1;i<=n;i++) s+=a[i];
	cout<<s<<endl;
	for (int i=p+1;i<n;i++)
	{
		printf("%d %d\n",a[p],a[i]);
		a[p]-=a[i];
	}
	printf("%d %d\n",a[n],a[p]);a[n]-=a[p];
	for (int i=1;i<p;i++)
	{
		printf("%d %d\n",a[n],a[i]);
		a[n]-=a[i];
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

 

  D:顯然A到B和B到A的過程是獨立的,分別最優化便可。顯然就是作一個徹底揹包。須要注意的是第二次徹底揹包值域是5000*5000,且答案會爆int。blog

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N (5010*5010)
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,a[2][3];
ll f[N];
ll solve(int x,int y,int n)
{
	for (int i=0;i<=n;i++) f[i]=i;
	for (int i=0;i<3;i++)
		for (int j=a[x][i];j<=n;j++)
		f[j]=max(f[j],f[j-a[x][i]]+a[y][i]);
	return f[n];
}//有n元錢 從x買入 y賣出 最後最多能剩多少 
signed main()
{
	n=read();
	for (int i=0;i<2;i++)
		for (int j=0;j<3;j++)
		a[i][j]=read();
	cout<<solve(1,0,solve(0,1,n));
	return 0;
	//NOTICE LONG LONG!!!!!
}
 

  E:設f[i][j]爲最大數是i且有j個時的方案數,尷尬的是轉移須要用到最小值數量,而且沒法記錄。但注意到從最小值中挑一個和把一個數變成最大值之一的過程是一一對應的,因此在新增最大值時直接將貢獻乘進去便可。那麼上面的dp容易獲得f[i][j]=f[i][j-1]*j,因而只要記錄f[i][1]並轉移。排序

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 1000010
#define P 1000000007
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,h,d,f[N],sum[N],s,t;
int ksm(int a,int k)
{
	int s=1;
	for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
	return s;
}
int inv(int a){return ksm(a,P-2);}
signed main()
{
	n=read(),h=read(),d=read();
	s=t=1;
	for (int i=2;i<=n;i++)
	{
		t=1ll*t*i%P;
		s=(s+t)%P;
	}
	f[0]=inv(s);sum[0]=f[0];
	for (int i=1;i<=h;i++)
	{
		int u=(sum[i-1]-(i>d?sum[i-d-1]:0)+P)%P;
		f[i]=1ll*u*s%P;
		sum[i]=(sum[i-1]+f[i])%P;
	}
	for (int i=n;i>=1;i--) f[h]=1ll*f[h]*i%P;
	cout<<f[h];
	return 0;
	//NOTICE LONG LONG!!!!!
}

  result:rank 98 rating +38get

相關文章
相關標籤/搜索