欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

信息学蒟蒻域ACM模拟赛题解

程序员文章站 2022-03-09 16:09:44
...

信息学蒟蒻域ACM模拟赛题解

因为x很大,我们可以考虑取对数(很好想的),然后就是比较x*log10(x)和log10(n!)之间的大小了。

其中后者我们可以利用斯特林公式(注意精度问题):

                                     信息学蒟蒻域ACM模拟赛题解

#include<map>     
#include<stack>            
#include<queue>            
#include<vector>    
#include<string>  
#include<math.h>            
#include<stdio.h>            
#include<iostream>            
#include<string.h>            
#include<stdlib.h>    
#include<algorithm>   
#include<functional>    
using namespace std;
typedef long long  ll;
#define inf  1000000000       
#define mod 1000000007             
#define maxn  286000  
#define PI 3.1415926
#define lowbit(x) (x&-x)            
#define eps 1e-9  
int main(void)
{
	double x, y=0,ans=0;
	ll  i;
	scanf("%lf", &x);
	if (x == 1)
	{
		printf("2\n");
		return 0;
	}
	x = x*log10(x)+1;
	double l = 0,r= 17777777778;
	while (r - l >= 0.000001)
	{
		double mid = (l + r) / 2.0;
		y = (double)(log10(2 * PI*mid) / 2 + mid*log10(mid / 2.718281828459));
		if (y - x >= eps)
		{
			ans = mid;
			r = mid;
		}
		else
			l = mid;
	}
	printf("%.0f\n", ans);
}

信息学蒟蒻域ACM模拟赛题解

这道题和BZOJ windy数一样,简单的数位DP搞搞就OK了。

#include<map>     
#include<stack>            
#include<queue>            
#include<vector>    
#include<string>  
#include<math.h>            
#include<stdio.h>            
#include<iostream>            
#include<string.h>            
#include<stdlib.h>    
#include<algorithm>   
#include<functional>    
using namespace std;
typedef long long  ll;
#define inf  1000000000       
#define mod 1000000007             
#define maxn  560050  
#define lowbit(x) (x&-x)            
#define eps 1e-9  
#define maxn 2000005
ll dp[30][15], len1, a, b, t[100];
ll work(ll x)
{
	int res = 0;
	while (x)
		t[++res] = x % 10, x /= 10;
	return res;
}
ll dfs(ll len, ll pos, ll flag, ll id)
{
	ll ans, num, i, j;
	if (len == 0)
		return 1;
	if (flag == 0 && dp[len][pos] != -1)
		return dp[len][pos];
	else
		ans = 0;
	if (flag)
		num = t[len];
	else
		num = 9;
	for (i = 0;i <= num;i++)
	{
		if (pos == -1 || abs(i - pos) >= 2)
		{
			if (i == 0 && id)
				ans += dfs(len - 1, -1, flag && i == num, i == 0 && id);
			else
				ans += dfs(len - 1, i, flag && i == num, i == 0 && id);
		}
	}
	if (flag == 0 && id == 0)
		dp[len][pos] = ans;
	return ans;
}
int main(void)
{
	ll a, b, i, j, ans1 = 0, ans2 = 0;
	memset(dp, -1, sizeof(dp));
	scanf("%lld%lld", &a, &b);
	len1 = work(a - 1);
	ans1 = dfs(len1, -1, 1, 1);
	len1 = work(b);
	ans2 = dfs(len1, -1, 1, 1);
	printf("%lld\n", ans2 - ans1);
	return 0;
}

信息学蒟蒻域ACM模拟赛题解

题解:一开始用的递推瞎搞搞,然后怎么测怎么对,陷入了无尽的绝望了,浪费了很长时间后,换了一种姿势,用了背包写了一发,直接AC,感觉又是玄学,但是没办法,背包的话很简单,定义dp[i][j]:表示当前选的集合里权值和为i且已经放了j个士兵的状态是否合法(合法为1,不合法为0),然后按照一般的背包递推就OK了。

#include<map>     
#include<stack>            
#include<queue>            
#include<vector>    
#include<string>  
#include<math.h>            
#include<stdio.h>            
#include<iostream>            
#include<string.h>            
#include<stdlib.h>    
#include<algorithm>   
#include<functional>    
using namespace std;
typedef long long  ll;
#define inf  1000000000       
#define mod 1000000007             
#define maxn  5600  
#define lowbit(x) (x&-x)            
#define eps 1e-9  
int dp[8205][205], a[205];
int main(void)
{
	int n, i, j, k, sum = 0, h;
	scanf("%d", &n);
	for (i = 1;i <= n;i++)
	{
		scanf("%d", &a[i]);
		sum += a[i];
	}
	dp[0][0] = 1;
	for (i = 1;i <= n;i++)
		for (j = 8000;j >= a[i];j--)
		{
			for (k = 1;k <= i;k++)
			{
				if (dp[j - a[i]][k - 1] == 0)
					continue;
				dp[j][k] = 1;
			}
		}
	int x=0, y;
	for (i = sum/2;i >= 0;i--)
		if (dp[i][n / 2] || dp[i][n / 2 + (n % 2 != 0)])
		{
			x = i;
			break;
		}
	y = sum - x;
	if (x > y) swap(x, y);
	if (n == 1)
		printf("0 %d\n", sum);
	else
		printf("%d %d\n", x, y);
	return 0;
}

信息学蒟蒻域ACM模拟赛题解

简单的kmp应用,当第一次匹配完成时直接break就好啦。。。

#include<map>     
#include<stack>            
#include<queue>            
#include<vector>    
#include<string>  
#include<math.h>            
#include<stdio.h>            
#include<iostream>            
#include<string.h>            
#include<stdlib.h>    
#include<algorithm>   
#include<functional>    
using namespace std;
typedef long long  ll;
#define inf  1000000000       
#define mod 1000000007             
#define maxn  560050  
#define lowbit(x) (x&-x)            
#define eps 1e-9  
char s1[maxn], s2[maxn];
ll p[maxn], q[maxn], ans;
void print()
{
	int i, j = 0;
	p[1] = 0;
	int len = strlen(s1 + 1);
	for (i = 2;i <= len;i++)
	{
		while (j>0 && s1[j + 1] != s1[i])
			j = p[j];
		if (s1[i] == s1[j + 1])
			j++;
		p[i] = j;
	}
}
void kmp()
{
	int i, j = 0, sum = strlen(s1 + 1);
	int len = strlen(s2 + 1);
	for (i = 1;i <= len;i++)
	{
		while (j>0 && s2[i] != s1[j + 1])
			j = p[j];
		if (s1[j + 1] == s2[i])
			j++;
		if (j == sum)
		{
			ans = i;
			j = p[j];
			break;
		}
	}
}
int main(void)
{
	int T, i, j;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%s", s2+1);
		scanf("%s", s1+1);
		print();kmp();
		printf("%lld\n", ans-strlen(s1+1)+1);
	}
	return 0;
}
信息学蒟蒻域ACM模拟赛题解

这道题算是A的最快的一道了,最优决策一定是唯一固定的,故我的一个做法是令右括号为‘-1’,左括号为‘1’,然后记录最大值,答案肯定是(最大值+1)/2,其实本质上就是当前括号左边有几个括号没有完成配对。。。。

#include<map>     
#include<stack>            
#include<queue>            
#include<vector>    
#include<string>  
#include<math.h>            
#include<stdio.h>            
#include<iostream>            
#include<string.h>            
#include<stdlib.h>    
#include<algorithm>   
#include<functional>    
using namespace std;
typedef long long  ll;
#define inf  1000000000       
#define mod 1000000007             
#define maxn  286000  
#define lowbit(x) (x&-x)            
#define eps 1e-9  
int main(void)
{
	char c;
	int i, sum = 0, mx = 0, n;
	scanf("%d", &n);
	for (i = 1;i<=n;i++)
	{
		scanf(" %c", &c);
		if (c == '(')
			sum -= 1;
		else
			sum += 1;
		mx = max(mx,abs(sum));
	}
	printf("%d\n", mx / 2 + (mx % 2 != 0));
	return 0;
}
信息学蒟蒻域ACM模拟赛题解

赛后补的一道题,单调栈用两次,一次求所有子序列的最小值,一次求最大值,然后相减即可。。

#include<map>       
#include<stack>              
#include<queue>              
#include<vector>      
#include<string>    
#include<math.h>              
#include<stdio.h>              
#include<iostream>              
#include<string.h>              
#include<stdlib.h>      
#include<algorithm>     
#include<functional>      
using namespace std;
typedef long long  ll;
#define inf  1000000000         
#define mod 1000000007               
#define maxn  386000    
#define PI 3.1415926  
#define lowbit(x) (x&-x)              
#define eps 1e-9    
struct node
{
	ll x, l, r, y;
}a[maxn];
stack<node>t;
int main(void)
{
	ll ans1 = 0, ans2 = 0;
	int n, i, j;
	scanf("%d", &n);
	for (i = 1;i <= n;i++)
		scanf("%lld", &a[i].x), a[i].y = i;
	for (i = 1; i <= n;i++)
	{
		a[i].l = i;
		while (t.empty() == 0 && t.top().x >= a[i].x)
		{
			a[t.top().y].r = i - 1;
			a[i].l = a[t.top().y].l;
			t.pop();
		}
		t.push(a[i]);
	}
	while (t.empty() == 0)
	{
		a[t.top().y].r = n;
		t.pop();
	}
	for (i = 1;i <= n;i++)
	{
		ans2 += a[i].x*(i - a[i].l + 1)*(a[i].r - i + 1);
		a[i].l = a[i].r = i;
	}
	for (i = 1; i <= n;i++)
	{
		a[i].l = i;
		while (t.empty() == 0 && t.top().x <= a[i].x)
		{
			a[t.top().y].r = i - 1;
			a[i].l = a[t.top().y].l;
			t.pop();
		}
		t.push(a[i]);
	}
	while (t.empty() == 0)
	{
		a[t.top().y].r = n;
		t.pop();
	}
	for (i = 1;i <= n;i++)
		ans1 += a[i].x*(i - a[i].l + 1)*(a[i].r - i + 1);
	printf("%lld\n", ans1 - ans2);
	return 0;
}




信息学蒟蒻域ACM模拟赛题解

这是一道经典题了,大二的时候做过,结论是C(2*n,n)-C(2*n,n-1);(注意要用逆元)

具体证明可以自行百度。。。。

#include<map>     
#include<stack>            
#include<queue>            
#include<vector>    
#include<string>  
#include<math.h>            
#include<stdio.h>            
#include<iostream>            
#include<string.h>            
#include<stdlib.h>    
#include<algorithm>   
#include<functional>    
using namespace std;
typedef long long  ll;
#define inf  1000000000       
#define mod 1000000007             
#define maxn  5600500  
#define lowbit(x) (x&-x)            
#define eps 1e-9  
ll fac[maxn], inv[maxn];
ll Pow(ll a, ll b)
{
	ll ans = 1;
	while (b)
	{
		if (b & 1)
			ans = (ans*a) % mod;
		a = (a*a) % mod;
		b >>= 1;
	}
	return ans;
}
int main(void)
{
	ll n, a, b;
	fac[0] = inv[0] = 1;
	for (int i = 1;i <= 2000005;i++)
	{
		fac[i] = (fac[i - 1] * i) % mod;
		inv[i] = Pow(fac[i], mod - 2);
	}
	scanf("%lld", &n);n = n - 1;
	ll ans1 = fac[2 * n] * inv[n] % mod*inv[n] % mod;
	ll ans2 = fac[2 * n] * inv[n + 1] % mod*inv[n - 1] % mod;
	printf("%lld\n", (ans1-ans2+mod)%mod);
	return 0;
}

信息学蒟蒻域ACM模拟赛题解

字典树模板题,手码+AC=5分钟。。。写的最快的一道字典树题,唯一的处理就是当前字符标记一下有多少字符串的前缀经过。

#include<map>     
#include<stack>            
#include<queue>            
#include<vector>    
#include<string>  
#include<math.h>            
#include<stdio.h>            
#include<iostream>            
#include<string.h>            
#include<stdlib.h>    
#include<algorithm>   
#include<functional>    
using namespace std;
typedef long long  ll;
#define inf  1000000000       
#define mod 1000000007             
#define maxn  286000  
#define lowbit(x) (x&-x)            
#define eps 1e-9  
int siz, a[maxn][30],cnt[maxn][30];
char s1[55], s2[55];
void insert()
{
	int i, j, now = 0,len=strlen(s2);
	for (i = 0;i < len;i++)
	{
		int v = s2[i] - 'a';
		if (a[now][v] == 0)
			a[now][v] = ++siz;		
		cnt[now][v]++;
		now = a[now][v];
	}
}
double query()
{
	double res = 0.0;
	int i, j, now = 0;
	int len = strlen(s2);
	for (i = 0;i < len;i++)
	{
		int v = s2[i]-'a';
		if (a[now][v] == 0)
			break;
		res += (double)(i+1)/(double)len*(double)cnt[now][v];
		now = a[now][v];
	}
	return res;
}
int main(void)
{
	int n,i,q;
	scanf("%d", &n);
	scanf("%s", s1);
	for (i = 1;i <= n;i++)
	{
		scanf("%s", s2);
		insert();
	}
	strcpy(s2, s1);
	printf("%.2f\n", query());
	scanf("%d", &q);
	while (q--)
	{
		scanf("%s", s2);
		printf("%.2f\n", query());
	}
	return 0;
}
信息学蒟蒻域ACM模拟赛题解

比赛签到题,我是拿递归写的。。。。

#include<map>     
#include<stack>            
#include<queue>            
#include<vector>    
#include<string>  
#include<math.h>            
#include<stdio.h>            
#include<iostream>            
#include<string.h>            
#include<stdlib.h>    
#include<algorithm>   
#include<functional>    
using namespace std;
typedef long long  ll;
#define inf  1000000000       
#define mod 1000000007             
#define maxn  560050  
#define lowbit(x) (x&-x)            
#define eps 1e-9  
ll work(ll x)
{
	if (x <= 1)
		return 0;
	return  work(x / 2 + (x % 2 != 0)) + 1;
}
int main(void)
{
	ll n;
	scanf("%lld", &n);
	printf("%lld\n", work(n));
	return 0;
}

信息学蒟蒻域ACM模拟赛题解

同样是水题,我们可以先计算出每条线的斜率,然后每次O(n)查找即可

#include<map>     
#include<stack>            
#include<queue>            
#include<vector>    
#include<string>  
#include<math.h>            
#include<stdio.h>            
#include<iostream>            
#include<string.h>            
#include<stdlib.h>    
#include<algorithm>   
#include<functional>    
using namespace std;
typedef long long  ll;
#define inf  1000000000       
#define mod 1000000007             
#define maxn  5600  
#define lowbit(x) (x&-x)            
#define eps 1e-9  
struct node
{
	double x, y, xx, yy,flag;
}a[maxn],b;
int main(void)
{
	int n, i, j, q;
	while (scanf("%lld", &n) != EOF)
	{
		for (i = 1;i <= n;i++)
		{
			scanf("%lf%lf%lf%lf", &a[i].x, &a[i].y, &a[i].xx, &a[i].yy);
			double t1, t2;
			if (a[i].x > a[i].xx)
				t1 = a[i].xx, t2 = a[i].yy, a[i].xx = a[i].x, a[i].yy = a[i].y, a[i].x = t1, a[i].y = t2;
			a[i].flag = (a[i].yy - a[i].y) / (a[i].xx - a[i].x);
		}
		scanf("%d", &q);
		while (q--)
		{
			int ans = 0;
			scanf("%lf%lf%lf%lf", &b.x, &b.y, &b.xx, &b.yy);
			b.flag = (b.yy - b.y) / (b.xx - b.x);
			for (i = 1;i <= n;i++)
				if (fabs(b.flag - a[i].flag) <= eps)
					ans++;
			printf("%d\n", ans);
		}
	}
	return 0;
}



相关标签: 比赛总结