ZOJ Monthly, March 2018 A B C J H

A Easy Number Game

贪心 很容易想到,将数列排序 将前2n个数 掐头去尾的相乘求和

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int T;
int n,m;
int s[100100];
int main()
{
	
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		for(int i=0;i<n;i++)
			cin>>s[i];
		sort(s,s+n);
		long long int res=0;
		for(int i=0;i<m;i++)
		{
			res+=s[i]*s[2*m-i-1];
		}
		cout<<res<<endl;
	}
	return 0;
}


B Lucky Man

卡在了第五题上,规律发现了 但是当时做不到快速的得到1000位长度的大整数的平方根而超时,现在已经解决,就是运用模拟笔算的方式得到,1880ms过了题,限制是2000ms

同时也知道了可以用Python直接输入大整数进行牛顿迭代的方法得到。

#include <stdio.h> 
#include <string.h> 
#include <iostream>
using namespace std;
int l; 
char an[1111];
int js=0;
int work(int o,char *O,int I) 
{ 
char c, *D=O ; 
if(o>0) 
{ 
for(l=0;D[l];D[l++]-=10) 
{ 
D[l++]-=120; 
D[l]-=110; 
while(!work(0,O,l)) 
D[l]+=20; 
an[js++]=(D[l]+1032)/20;
} 
} 
else 
{ 
c=o+(D[I]+82)%10-(I>l/2)*(D[I-l+I]+72)/10-9; 
D[I]+=I<0 ? 0 : !(o=work(c/10,O,I-1))*((c+999)%10-(D[I]+92)%10); 
} 
return o; 
} 

int main() 
{ 
int t;
cin>>t;
while(t--)
{
char s[1200]={};s[0]='0'; 
scanf("%s",s+1); 
js=0;
if(strlen(s)%2 == 1) 
work(2,s+1,0); 
else 
work(2,s,0); 
if((an[js-1]-'0')%2==1)cout<<"1"<<endl;
else cout<<"0"<<endl; 
}
return 0; 
}


C Travel along the Line

概率题,在无现长数轴上,给定起点和终点的距离,给出时间,每一秒有0.25的概率前进,0.25的概率后退,0.5的概率不懂,问在时间用完的时候恰好在终点的概率。 当时列了个式子,想着用lucas算法去解大组合数,结果超时,后来把式子化简一下,打了个阶乘表,就过了,以后碰到10e5以内的组合数 优先考虑打表。


#include<bits/stdc++.h>
using namespace std;
#define LL long long 
LL p = 1e9+7;
LL quick_mod(LL a, LL b)
{
    LL ans = 1;
    a %= p;
    while(b)
    {
        if(b & 1)
        {
            ans = ans * a % p;
            b--;
        }
        b >>= 1;
        a = a * a % p;
    }
    return ans;
}

long long  jc[100005];

LL inv(LL a)
{
	if(a==1)return 1;
	return inv(p%a)*(p-p/a)%p;
}
int main(){
	long long int n,m;
	jc[0]=1;
	for(int i=1;i<=100000;i++)
	{
		jc[i]=i*jc[i-1]%p;
	}
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		m=abs(m);
		long long int ans=0;
		for(int i=n-m;i>=0;i-=2)
		{
			long long in=quick_mod(2,2*n-i);
			long long a1=jc[(n-i-m)/2]*jc[(n-i+m)/2]%p;
			a1=a1*jc[i]%p;
			ans=(ans+jc[n]%p*inv(in*a1%p)%p)%p;
		}
		cout<<ans<<endl;
	}
	return 0;
}


H Happy Sequence

dp题,从1到n 求长度为m的good数列的个数,即数列中前一个数可以整除后面一个数,主要思路就是将长度为k的某个数列的最后一个数能整除的数放到后面 使该数列的长度变为k+1,从而可以写出状态转移方程。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int mod=1000000007;
int T;
int n,m;
int dp[2002][2002];
vector<int> fac[2002];
int main()
{
    for(int i=1;i<=2000;i++)
	{
		for(int j=1;j<=sqrt(i*1.0);j++)
		{
			if(i%j==0)
			{
				fac[i].push_back(j);
				if(j!=i/j)
				fac[i].push_back(i/j);
			}
		}
	}
	memset(dp,0,sizeof(dp));
	for(int i=0;i<=2000;i++)
		dp[i][1]=1;
	for(int i=2;i<=2000;i++)
	{
		for(int j=1;j<=2000;j++)
		{
			for(int k=0;k<fac[j].size();k++)
			{
				(dp[j][i]+=dp[fac[j].at(k)][i-1])%=mod;
			}
		}
	}
	for(int i=1;i<=2000;i++)
	{
		for(int j=2;j<=2000;j++)
		{
			(dp[j][i]+=dp[j-1][i])%=mod;
		}
	}
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		cout<<dp[n][m]<<endl;
	}
	return 0;
}


J Super Brain

快速找出2个数列中出现2次的数,数据范围很小,所以很简单。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
int T,x;
int n,m;
bool s[1000100];
int main()
{
	
	cin>>T;
	while(T--)
	{
		cin>>n;
		memset(s,0,sizeof(s));
		for(int i=0;i<n;i++)
		{
			cin>>x;
			s[x]=1;
		}
		for(int i=0;i<n;i++)
		{
			cin>>x;
			if(s[x])
				cout<<x<<endl;
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值