AtCoder Beginner Contest 173 A-F

A:水题

#include 
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/

int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
	int n;
	cin>>n;
	cout<<(1000-n%1000)%1000<

B:水题

#include 
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
char s[M];
int c[4];

int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int n;
  	cin>>n;
  	for(int i=1;i<=n;i++)
  	{
  		cin>>s;
  		if(s[0]=='A')c[0]++;
  		else if(s[0]=='W')c[1]++;
  		else if(s[0]=='T')c[2]++;
  		else c[3]++;
	  }
	cout<<"AC x "<

C:二进制暴力枚举即可

#include 
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
char s[10][10];
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int h,w,k;
  	cin>>h>>w>>k;
  	for(int i=0;i>s[i];
  	int ans=0;
  	for(int i=0;i<(1<>a&1)continue;
  			if(j>>b&1)continue;
  			if(s[a][b]=='#')tp++;
		}
		if(tp==k)ans++;
	}
	cout<

D:显然大的先放能得到的价值更大。

除了最大值只能得到一次贡献外, 其他每个值最多贡献2次(一左一右)

所以肯定优先取最大的数贡献。

#include 
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 2e5+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int a[M];
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int n;
  	cin>>n;
  	for(int i=1;i<=n;i++)cin>>a[i];
  	sort(a+1,a+1+n);
  	ll ans=a[n];
  	int nm=n-2;
  	for(int i=n-1;i>=1;i--)
  	{
  		if(nm>1)nm-=2,ans+=a[i]*2;
  		else if(nm==1)nm=0,ans+=a[i];
  		else break;
	}
	cout<

E:

分情况即可:

1:0必须取

2:除了0之外的数全部取光

3:只有负数,且负数个数是奇数

4:否则一定可以构造出正数。正数最大的两个乘积与负数最小两个乘积不断相比较即可。

#include 
using namespace std;
typedef long long ll;
const int M = 2e5+7;
const int mod =1e9+7;
ll pz[M],pf[M];
ll z[M],f[M];
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);
  	int n,k;cin>>n>>k;
  	int nm=0;//0的数量 
	int zm=0,fm=0;
  	for(int i=1;i<=n;i++)
  	{
  		int x;cin>>x;
  		if(x>0)z[++zm]=x;
  		else if(x<0)f[++fm]=-x;
  		else nm++;
	}
  	sort(z+1,z+1+zm);
  	sort(f+1,f+1+fm);
  	if(n-k=2)
		{
			if((q>=2 && z[q]*z[q-1]>f[w]*f[w-1])||w<2)
			{
				ans=ans*z[q]%mod;
				ans=ans*z[q-1]%mod;
				q-=2;
			}
			else
			{
				ans=ans*f[w]%mod;
				ans=ans*f[w-1]%mod;
				w-=2;
			}
			nw+=2;
		}
		else if(k-nw==1)
		{
			ans=ans*z[q]%mod,q--;
			nw++;
		}
		else break;
	}
	cout<< ans<

F:假设刚开始n个点,0条边。则结果很简单。

考虑每次加入一个边 u -> v ,(u=v)的结果减一 ;

因为:u,v此时一定不连通(这是一颗树)。然后连边使得u所在联通块与v所在联通块连通。

则在S同时包括u,v时,答案会减一。(联通块减一)

综上:直接枚举减去贡献即可

#include 
using namespace std;
typedef long long ll;
const int M = 2e5+7;
const int mod =1e9+7;
ll pz[M],pf[M];
ll z[M],f[M];
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);
  	int n;
	cin>>n;
	ll ans=0;
	for(int i=1;i<=n;i++)ans+=(ll)i*(n-i+1);
	for(int i=1;i>u>>v;
		if(u>v)swap(u,v);
		ans-=u*(n-v+1);
	 } 
	 cout<

 

你可能感兴趣的:(atcoder,技巧思维题)