首页 > 其他分享 >NOIP模拟测试A3

NOIP模拟测试A3

时间:2023-06-14 09:15:19浏览次数:35  
标签:std cnt NOIP int sum long A3 include 模拟

A. 谜之阶乘

题目是让我们把 \(n\) 分解成两个阶乘的商,本来想推个式子什么的,结果发现推不出来。

我们知道,阶乘的增长速率非常的快啊!那么这个 \(b - a\) 的值肯定不会太大,我们可以暴力枚举 \(b - a\) 的值。

假设我们选择 \(5\) 个连续的正整数的乘积为 \(n\),那么他们的值都在 \(\sqrt[5]{n}\) 附近。

那么假设 \(d = b - a\),显然有 \(\displaystyle a < \sqrt[d]{n}\),\(\displaystyle b < \sqrt[d]{n}\)。

我们就可以直接在 \(\sqrt[d]{n}\) 附近的范围枚举,枚举 \(20\) 个就差不多了。

复杂度大概是 \(\displaystyle O(T \ \text{log}_2^2 \ n)\)。

Code:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#define int long long

int T;
int n;

struct Node{
	int first,second;
	
	friend bool operator<(Node a,Node b) {
		return a.first < b.first;
	}
}res[100500];

int cnt;

signed main() {
	std::cin >> T;
	while(T--) {
		std::cin >> n;
		if(n == 1) {
			std::cout << "-1\n";
			continue;
		}
		cnt = 1;		
		res[cnt] = (Node){n,n - 1};
		for(int i = 2;i <= 63; i++) {
			int x = pow((double)n,(double)1 / (double)i);
			while(1) {
				int y = x - i + 1;
				int k = 1;
				for(int i = y;i <= x; i++)
					k *= i;
				
				if(k > n)
					break;
				
				if(k == n && y - 1 != 0) {
					cnt ++;
					res[cnt] = (Node){x,y - 1};
					break;
				}
				x ++;
			}
		}

		std::cout << cnt << "\n";
		for(int i = cnt;i >= 1; i--)
			std::cout << res[i].first << " " << res[i].second << "\n";
	}
	return 0;
}

B. 子集

记 \(m = \dfrac{n}{k}\)。

首先判掉无解的情况。

\(m = 1\) 时显然是无解的。

若 \(1\) 到 \(n\) 之和不是 \(k\) 的倍数,肯定无法分成相等的集合,也无解。

若 \(n\) 为偶数而 \(m\) 是奇数,也就符合了上面说的那种情况,无解。

再特判一下 \(k = 1\) 的情况,直接输出就可以了。

考虑 \(m\) 为偶数,那么我们可以直接将 \(i\) 与 \(n - i\) 配对,显然这样各集合元素之和是相等的。

若 \(n,m\) 均为奇数,我们把 \(m\) 看作 \(2x + 3\),对于 \(2x\) 我们像之前那样处理,只是特殊处理出前三列。

然后进行构造。

复杂度 \(O(n)\)。
Code:

#include <bits/stdc++.h>

using namespace std;

#define int long long

int T,n,k,m;

long long sum,cnt;
  
int l;

std::vector<int> f[500500];

signed main() {
    cin >> T;
    while(T--) {
        for(int i = 0;i < 500500; i++)
            f[i].clear();
        cin >> n >> k;
        m = n / k;
        sum = n * (n + 1) / 2;

        if(k == 1) {
            printf("Yes\n");
            for(int i = 1;i <= n; i++)
                cout << i << " ";
            cout << endl;
            continue;
        }

        if(sum%k != 0 || m == 1 || n == k) {
            // 有 n 组,不可能各组和相等  
            cout << "No" << endl;
            continue;
        }

        if(n&1 == 0 && m&1 != 0) {
            // 1 到 n 的和肯定不是 k 的倍数  
            cout << "No" << endl;
            continue;
        }

        cout << "Yes\n";
        if(m&1) {// m 为奇数  
            for(int i = 1;i <= (m - 3)/2; i++) {
                l = (i - 1) * 2 * k;
                for(int j = 1;j <= k; j++)
                    f[j].push_back(l + j);

                for(int j = k;j >= 1; j--)
                    f[j].push_back(l + 2 * k - j + 1);
            }

            l = (m - 3) * k;

            for(int i = 1;i <= k; i++)
                f[i].push_back(l + i);

            l = l + k;

            for(int i = (k - 1)/2 + 1; i <= k; i++)
                f[i].push_back(l + i - (k - 1)/2);

            for(int i = 1;i <= (k - 1)/2; i++)
                f[i].push_back(l + k - (k - 1)/2 + i);

            for(int i = (k - 1)/2 + 1,m = n;i <= k; i++, m -= 2)
                f[i].push_back(m);

            for(int i = 1,m = n - 1;i <= (k - 1)/2; i ++ ,m -= 2)
                f[i].push_back(m);

            for(int i = 1;i <= k; i++) {
                for(int j = 0;j < f[i].size(); j++)
                    cout << f[i][j] << " ";
                cout << endl;
            }
        }
        else {
            for(int i = 1;i <= k; i++) {
                for(int j = 1;j <= (m/2); j++) {
                    int l = 2 * (j - 1);
                    cout << (l * k + i) << " " << ((l | 1)*k + k - i + 1) << " ";
                }
                cout << endl;
            }
        }
	}
    return 0;
}
/*
Input:
4
4 4
4 1
12 3
9 3
*/

C. 混凝土粉末

把询问离线,在序列下标上执行扫描线,开一棵以询问编号为下标的树状数组。

扫到一个修改的左端点时,在树状数组上二分,扫到左端点加 \(h[i]\),扫到右端点时减去。

扫到询问时,在树状数组上二分。
Code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#define int long long

using namespace std;

const int N = 2005000;

int n,q;
int opt[N],res[N];

vector< pair<int,int> > g[N],h[N];

class BIT{
	private:
		int bit[N];
		
		int lowbit(int x) {
			return x & (-x);
		}
	public:
		void Add(int x,int y,int val) {
			for(int i = x;i <= y; i += lowbit(i))
				bit[i] += val;
		}
		
		int Query(int x) {
			int ans = 0;
			
			for(int i = x;i; i -= lowbit(i))
				ans += bit[i];
				
			return ans;
		}
}tree;

signed main() {
	cin >> n >> q;
	for(int i = 1,l,r,x,y;i <= q; i++) {
		cin >> opt[i];
		if(opt[i] == 1) {
			cin >> l >> r >> x;
			g[l].push_back(make_pair(i,x));
			g[r + 1].push_back(make_pair(i,-x));
		}
		else {
			cin >> x >> y;
			h[x].push_back(make_pair(i,y));
		}
	}
	
	for(int i = 1;i <= n; i++) {
		for(int j = 0;j < g[i].size(); j++)
			tree.Add(g[i][j].first,q,g[i][j].second);
		
		for(int j = 0;j < h[i].size(); j++) {
			int l = 1,r = h[i][j].first,mid;
			
			while(l < r) {
				mid = (l + r) >> 1;
				if(tree.Query(mid) >= h[i][j].second)
					res[h[i][j].first] = r = mid;
				else
					l = mid + 1;
			}
		}
	}
	
	for(int i = 1;i <= q; i++)
		if(opt[i] == 2) 
			cout << res[i] << endl;
	return 0;
} 

D. 排水系统



Code:

#include <bits/stdc++.h>

#define int long long

const int N = 20090500;
const int MOD = 998244353;

int n,m,r,k;

struct Edge{
	int next,to,val;
}e[N];

int h[N],cnt;

int in[N],out[N],sum;

int inv[N],inverse;

int f[N][2];

std::queue<int> que;

void Add(int u,int v,int w) {
	cnt ++;
	e[cnt].next = h[u];
	h[u] = cnt;
	e[cnt].to = v;
	e[cnt].val = w;
	return ;
}

int pow(int a,int b) {
	int ans = 1;
	while(b) {
		if(b&1)
			ans *= a;
		ans %= MOD;
		a *= a;
		a %= MOD;
		b >>= 1;
	}
	return ans;
}

void Input() {
	std::cin >> n >> m >> r >> k;
	
	for(int i = 1,u,v,w;i <= k; i++) {
		std::cin >> u >> v >> w;
		Add(u,v,w);
		
		in[v] ++;
		out[u] ++;
		
		sum += w;
		sum %= MOD;
	}
	return ;
}

void Ready() {
	
	inverse = pow(sum,MOD - 2);
	std::cerr << inverse <<"\n";
	inv[1] = 1;
	for(int i = 2;i <= k; i++)
		inv[i] = (long long)(MOD - MOD / i) * inv[MOD % i] % MOD;
	
	for(int i = 1;i <= n; i++)
		if(!in[i])
			que.push(i);
	
	for(int i = 1;i <= m; i++)
		f[i][0] = f[i][1] = 1;
	return ;
}

void Work() {
	while(!que.empty()) {
		int x = que.front();
		que.pop();
		int tot = 0;
		
		for(int i = h[x];i; i = e[i].next) {
			int to = e[i].to;
			in[to] --;
			
			if(!in[to])
				que.push(to);
			
			f[to][1] = (f[to][1] + (long long)f[x][1] % MOD * inv[out[x]] % MOD) % MOD;
			f[to][0] = (f[to][0] + (long long)f[x][0] % MOD * inv[out[x]] % MOD) % MOD;
			
			tot = (tot + (long long)f[x][0] % MOD * inverse % MOD * e[i].val % MOD * inv[out[x] - 1] % MOD * inv[out[x]]) % MOD;
		}
		
		for(int i = h[x];i; i = e[i].next) {
			int to = e[i].to;
			
			f[to][1] = (f[to][1] + tot - (long long)f[x][0] % MOD * inverse % MOD * e[i].val % MOD * inv[out[x] - 1] % MOD * inv[out[x]] % MOD + MOD) % MOD;
			f[to][1] = (f[to][1] + MOD - (long long)f[x][0] % MOD * inverse % MOD * e[i].val % MOD * inv[out[x]] % MOD) % MOD;
		}
	}
	
	return ;
}

void Output() {
	for(int i = n - r + 1;i <= n; i++)
		std::cout << (f[i][1] + MOD) % MOD << " ";
	return ;
}

signed main() {
	Input();
	
	Ready();
	
	Work();
	
	Output();
	return 0;
}

标签:std,cnt,NOIP,int,sum,long,A3,include,模拟
From: https://www.cnblogs.com/baijian0212/p/noip-a3.html

相关文章

  • SAS模拟盘片状态
    Linuxhasaniftywayofallowingdiskstatemodificationvia/sys/interface.VeryusefulwhendebuggingLVMmirroring,diskdisasterrecoveryetc.ToputaSATAdiskoffline/running:echooffline>/sys/block/sda/device/stateechorunning>/sys/b......
  • 2023冲刺国赛模拟17
    最近的题题解咕了好多,看着补吧。。。A.掌分治直接按照连通块考虑没啥前途,根据期望的线型性,把贡献看成点对的贡献设\(f_{i,j}\)表示当\(i\)为根时,\(j\)在其所在连通块的概率求总和即为答案考虑实际上限制的是\(i\)是\(i-j\)路径上第一个删掉的点,那么概率就是路......
  • 【数字信号】基于matlab模拟GPS信号频谱
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 基于matlab模拟量子密钥分发密钥率仿真
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 一套最全的突破tls/ja3指纹的方案
    访问这个网站可以查看自己ja3信息  https://tls.browserleaks.com/json方法一pipinstallcurl_cffi#https://github.com/yifeikong/curl_cffifromcurl_cffiimportrequests#注意impersonate这个参数r=requests.get("https://tls.browserleaks.com/json",......
  • 【解决方法】锐捷EVE-ng模拟器中VPC无法通过DHCP获取IP地址,改用接口获取地址
    环境:工具:锐捷EVE模拟器,VMwareWorkstationPro远程工具:SecureCRT系统版本:Windows10问题描述:描述:一个简单的DHCP环境,使用VPC充当PC客户机,IP地址获取为DHCP方式。但在发送request数据包后,服务器服务器已经把地址租用出去,但VPC中并没有收到ACK数据包,并没有正常获取到IP地址......
  • 【考后总结】6 月西安多校模拟赛 1
    6.11冲刺国赛模拟16T3多边形凸多边形说明合法方案中同一种向量必须连续且多种顺序只算一个,因此直接计算各个向量选择的个数。设第\(i\)个向量选了\(c_i\)个,按照两个方向的正负分,可以写作:\[\sum_{x_i>0}c_ix_i=-\sum_{x_i<0}c_ix_i\lem\]\(y\)类似。于是相当于构......
  • NOIP模拟A2
    好像是去年8月1日的模拟赛,主题采自南昌起义。背景A.南一道可爱的期望DP。一般来说,期望DP都是逆推,从最终状态往前推,这题也不例外。这道题难度主要在于,第\(k\)次购买的价格为\(k\),即价格与购买次数有关。那我们就不能直接进行转移了,而是需要根据期望次数进行转移......
  • 尚医通-day06【医院模拟系统接口详细步骤】(内附源码)
    第01章-医院系统1、业务功能描述资料:资料>医院模拟系统>尚医通API接口文档.docx1.1、平台方参考《尚医通API接口文档.docx》进行业务接口的开发,接收医院方的接口调用,将医院信息、科室信息、排班信息等数据存入MongoDB。1.2、医院方每个医院有自己的业务平台,需参考《尚医通AP......
  • 数据结构模拟器地址
    数据结构在线模拟器 Github网址:https://github.com/IACJ/react-datastructer在线网址:https://iacj.github.io/react-datastructer/#/  这个在线的模拟器包含“栈”、“队列”、“堆”、“BST”等数据结构,每个数据结构以图像的方式展示在我们面前,同时又有各自的帮助文......