ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

一次模拟赛

2021-05-11 20:34:13  阅读:114  来源: 互联网

标签:ch int long times 一次 include 模拟 define


前沿

预计得分 \(30 + 100 + 0\)
实际得分 \(30 + 80 + 0\)
原因:我觉得是机房机子慢,放洛谷上不到 \(1s\) 就过了,在机房时限 \(2s\) 都过不去(哈哈,主要是把 \(std\) 给 \(gan\) 掉了)

T1 没有脑子的高精度

就真的,只为了考个高精度,绝了

给定 \(n\) 个数 \(a_i\) ,输出 \(\sum_{i=1}^{n}a_i!\) \(n,a_i\leq 100\)

【solution】:

我们直接预处理一下 \(a_i!\) 时间复杂度正确性显然,但是当 \(a_i = 25\) 左右的时候,你的 \(long \ \ long\) 就已经炸掉了,所以需要写高精度,不过谁能想到高精度竟然占到 \(70\) 分。

【Code】

无高精度的 \(30\) 代码

/*
By:Zmonarch
知识点 :
竟然考高精度,没想到没想到,打个 30 跑  
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define int unsigned long long 
#define qwq register 
#define inf 2147483647 
const int kmaxn = 1e6 + 10 ; 
const int kmod = 998244353 ; 
inline int read() {
	int x = 0 , f = 1 ; char ch = getchar() ; 
	while(!isdigit(ch)) {if(ch == '-') f = - 1 ; ch = getchar() ;}
	while( isdigit(ch)) {x = x * 10 + ch - '0' ; ch = getchar() ;}
	return x * f ; 
}
signed main(){
	freopen("a.in" , "r" , stdin) ; 
	freopen("a.out" , "w" , stdout) ; 	
	int n = read() , ret = 0 ;
	for(qwq int i = 1 ; i <= n ; i++) 
	{
		int x = read() , tmp = 1 ; 
		for(qwq int j = 1 ; j <= x ; j++) tmp *= j ; 
		ret += tmp ; 
	}
	printf("%lld\n" , ret) ; 
	return 0 ; 
}

高精度 : 这里给一下 \(std\) , 我抽空专门去搞一下高精度

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int, int> PII;
#define fi first
#define se second
#define MP make_pair

int read()
{
    int v = 0, f = 1;
    char c = getchar();
    while (c < 48 || 57 < c) {if (c == '-') f = -1; c = getchar();}
    while (48 <= c && c <= 57) v = (v << 3) + v + v + c - 48, c = getchar();
    return v * f;
}

int n;

struct B
{
    int a[500], len;
    B()
    {
        for (int i = 0; i < 500; i++)
            a[i] = 0;
        len = 0;
    }
} fac[200];

B operator + (const B &a, const B &b)
{
    B c;
    c.len = max(a.len, b.len);
    for (int i = 0; i <= c.len; i++)
        c.a[i] = a.a[i] + b.a[i];
    for (int i = 0; i <= c.len; i++)
        if (c.a[i] >= 10)
        {
            c.a[i + 1]++;
            c.a[i] -= 10;
        }
    if (c.a[c.len + 1])
        c.len++;
    return c;
}

B operator * (const B &a, const int &b)
{
    B c;
    c.len = a.len;
    for (int i = 0; i <= c.len; i++)
        c.a[i] = a.a[i] * b;
    for (int i = 0; i <= c.len + 10; i++)
    {
        c.a[i + 1] += c.a[i] / 10;
        c.a[i] %= 10;
    }
    for (int i = c.len + 10; i >= 0; i--)
    	if (c.a[i])
    	{
    		c.len = i;
    		break;
		}
    return c;
}

int main()
{
    freopen("a.in", "r", stdin);
    freopen("a.out", "w", stdout);
    n = read();
    fac[0].a[0] = 1;
    for (int i = 1; i <= 100; i++)
        fac[i] = fac[i - 1] * i;
    B ans;
    while (n--)
        ans = ans + fac[read()];
    for (int i = ans.len; i >= 0; i--)
        printf("%d", ans.a[i]);
    puts("");
}

T2 容斥原理板子题

我和个 \(der\) 一样

给 \(n\times m\) 的矩形染色,每一个点都有 \(k\) 种颜色,求没有任意一
行或任意一列颜色相同的方案数。并对 \(998244353\) 取膜

【Solution】:

我们考虑当直接去求这个方案数,显然是不大可行的。所以我们考虑一下他的补集,最后减去就好了。

  • 全集 : \(k^{n\times m}\) ,也就是 \(n\times m\) 个点随便染色。

我们考虑删掉 \(n\) 行中有任意 \(1\) 行颜色相同的方案数。但是这个时候,我们删多了,所以我们需要将任意两行颜色相同的方案数加回来,我们在删或减得时候,不要考虑的太多,眼前事眼前做就好。
我们不难发现这个一个容斥原理,所以前面的系数这是显然的 \(-1^k\)
也就是当为奇数的时候,我们删,为偶数时候,加回来。

我们考虑当前行的时候 :
我们就有这么个式子表示当前有 \(i\) 行的颜色是相同的方案数 :

  • 随机在 \(n\) 中选择 \(i\) 行 \(\times\) 在这 \(i\) 行中有多少种颜色 \(\times\) 剩下的矩阵随便排的方案数 。
  • 表达式为 \(C_{n}^{i}\times k^i \times k^{(n - i )\times m}\)

我们考虑一下列时候
我们发现和行是一样的,你可以将矩形旋转 \(90'\) 看和上述的玩意是一样的。无非是将上面的行换成了列而已吧

  • 表达式 : \(C_{m}^{i} \times k^{i} \times k^{(m - i)\times n}\)

这个才是最难的。 既有行又有列的时候,

我们这波套式子 :

  • 文字表达式为 \(k\) 种颜色 $\times $ 每一种颜色对应的方案数
    即为 :

\[k\sum_{i =1}^{n}\sum_{j=1}^{m}C_{n}^{i}C_{m}^{j} k^{(n - i)(m - j)} \]

然后吧,这个题的 \(n,m\leq 10^6\) 显然不可过,那么我们搞一下

\[k\sum_{i=1}^{n}C_{n}^{i}\sum_{j=1}^{m}C_{m}^{j}k^{(n - i)(m - j)} \]

你的,把 \(k^{n-i}\) 当做一个整体 \(w\) ,然后,这是一个非常显然的二项式定理,就可过了

\[k\sum_{i=1}^{n}C_{n}^{i}\times ((k^{n - i} - 1)^{m} - k^{(n - i)\times m}) \]

【Code】

/*
By:Zmonarch
知识点 :  
一开始以为是个简单的快速幂 + 组合数 , 结果样例过不去,55 ,容斥原理、  
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define int long long 
#define qwq register 
#define inl inline 
#define inf 2147483647 
const int kmaxn = 1e6 + 10 ; 
const int kmod = 998244353 ; 
inline int read() {
	int x = 0 , f = 1 ; char ch = getchar() ; 
	while(!isdigit(ch)) {if(ch == '-') f = - 1 ; ch = getchar() ;}
	while( isdigit(ch)) {x = x * 10 + ch - '0' ; ch = getchar() ;}
	return x * f ; 
}
int f[kmaxn] , Inv[kmaxn] ; 
int n , m , k ;
void init() {
	f[0] = 1 ; Inv[0] = Inv[1] = 1 ;
	for(qwq int i = 1 ; i <= 1000000 ; i++) f[i] = f[i - 1] * i % kmod ; 
	for(qwq int i = 2 ; i <= 1000000 ; i++) Inv[i] = (- kmod / i + kmod) * Inv[kmod % i] % kmod ; 
	for(qwq int i = 1 ; i <= 1000000 ; i++) Inv[i] = Inv[i - 1] * Inv[i] % kmod ; 
} 
int quick(int a , int b) {
	int ret = 1 ; 
	while(b) 
	{
		if(b & 1) ret = ret * a % kmod ; 
		a = a * a % kmod ; 
		b >>= 1 ; 
	}
	return ret ; 
}
int C(int n , int m) {return f[n] * Inv[m] % kmod * Inv[n - m] % kmod ;} 
signed main(){
	freopen("b.in" , "r" , stdin) ; 
	freopen("b.out" , "w" , stdout) ; 	
	init() ; n = read() , m = read() , k = read() ;
	int ans = quick(k , n * m) ;
	for(qwq int i = 1 ; i <= n ; i++) //同行的
	{
		// 容斥原理,前面的系数为(-1)^ i 
		if(i & 1) ans = (ans - C(n , i) * quick(k , i) % kmod * quick(k , (n - i) * m) % kmod + kmod) % kmod ; 
		else      ans = (ans + C(n , i) * quick(k , i) % kmod * quick(k , (n - i) * m) % kmod + kmod) % kmod ; 
	}
	for(qwq int i = 1 ; i <= m ; i++) //我判断一下同行的,将 m 和 n 换换 
	{
		if(i & 1) ans = (ans - C(m , i) * quick(k , i) % kmod * quick(k , (m - i) * n) % kmod + kmod) % kmod ; 
		else      ans = (ans + C(m , i) * quick(k , i) % kmod * quick(k , (m - i) * n) % kmod + kmod) % kmod ; 
	} 
	for(qwq int i = 1 ; i <= n ; i++) // 既有行又有列的情况 
	{
		if(i & 1) ans = (ans - C(n , i) * k % kmod * ((quick(quick(k , n - i) - 1 , m ) - quick(k , (n - i) * m) + kmod )) % kmod  + kmod) % kmod ; 
		else      ans = (ans + C(n , i) * k % kmod * ((quick(quick(k , n - i) - 1 , m ) - quick(k , (n - i) * m) + kmod )) % kmod  + kmod) % kmod ; 

	}
	printf("%lld\n" , ans) ;
	return 0 ; 
}

T3 看不懂的题目

你需要设计一套纸币系统,现在已经有了 \(n\) 种不同样式的纸币,
你只需要为它们设计面值。每种纸币的面值都是 \(B\) 的约数(不同种纸
币面值可以相同),但是 \(B\) 还未知,只知道 \(L<=B<=R\),在这个国家,
支付时会给定 \(d\),只要支付的总额模 \(K\) 与 \(d\) 同余即可。为了让人们能
应对支付时给出不同 d 的所有情况(假设可以使用的纸币没有限制),
请问你在 \(B\) 取值的所有可能性下设计方案数的和。对 \(998244353\) 取膜

【solution】:

如题面 : 看不懂。

教训 :

  1. 考试不要乱翻机子, 浪费时间
  2. 学会高精度,谁能想到高精度竟然占了 \(70\) 分。

标签:ch,int,long,times,一次,include,模拟,define
来源: https://www.cnblogs.com/Zmonarch/p/14757193.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有