[HNOI2002]跳蚤 【容斥】

摘要:
题目描述Z城市居住着很多只跳蚤。一只跳蚤将被请上一个高空钢丝的正中央。节目主持人会给该跳蚤发一张卡片。卡片上写有N+1个自然数。而他最终的任务是跳到距离他左边一个单位长度的地方,并捡起位于那里的礼物。而持有卡片的跳蚤,则怎么也不可能跳到距他左边一个单位长度的地方。当确定N和M后,显然一共有MN张不同的卡片。1≤N≤M≤1081leNleMle10^81≤N≤M≤108,且MN≤1016MNle10^{16}MN≤1016。

题目描述

Z城市居住着很多只跳蚤。在Z城市周六生活频道有一个娱乐节目。一只跳蚤将被请上一个高空钢丝的正中央。钢丝很长,可以看作是无限长。节目主持人会给该跳蚤发一张卡片。卡片上写有N+1个自然数。其中最后一个是M,而前N个数都不超过M,卡片上允许有相同的数字。跳蚤每次可以从卡片上任意选择一个自然数S,然后向左,或向右跳S个单位长度。而他最终的任务是跳到距离他左边一个单位长度的地方,并捡起位于那里的礼物。

比如当N=2,M=18时,持有卡片(10, 15, 18)的跳蚤,就可以完成任务:他可以先向左跳10个单位长度,然后再连向左跳3次,每次15个单位长度,最后再向右连跳3次,每次18个单位长度。而持有卡片(12, 15, 18)的跳蚤,则怎么也不可能跳到距他左边一个单位长度的地方。

当确定N和M后,显然一共有MN张不同的卡片。现在的问题是,在这所有的卡片中,有多少张可以完成任务。

输入输出格式

输入格式:

输入文件有且仅有一行,包括用空格分开的两个整数N和M。

输出格式:

输出文件有且仅有一行,即可以完成任务的卡片数。

1NM1081le Nle Mle 10^81NM108,且MN1016MNle 10^{16}MN1016

输入输出样例

输入样例#1:复制
2 4
输出样例#1:复制
12

说明

这12张卡片分别是:

(1, 1, 4), (1, 2, 4), (1, 3, 4), (1, 4, 4), (2, 1, 4), (2, 3, 4),

(3, 1, 4), (3, 2, 4), (3, 3, 4), (3, 4, 4), (4, 1, 4), (4, 3, 4)

题解
这道题解题的思维量不小,且涵盖了较多数论知识点,是一道好题,记录下来【02年省选题就那么难了么QAQ】
由N + 1个数组合能跳到左边一格,由扩欧我们知道,这是互质的充要条件
所以M和前N个数至少有一对互质
直接讨论发现很麻烦,我们就反过来,用总方案 - 所有数不互质的方案数
总方案M^N个很明显了,如果所有数不互质,它们至少有一个公共的质因子,所以我们枚举M的质因子
假设M = 30 = 2 * 3 * 5
我们设它们共有2,就总共有(M/2)^N种可能【M/2表示M中有多少2的倍数】
我们设它们共有3,就总共有(M/3)^N种可能
我们设它们共有5,就总共有(M/5)^N种可能
不对啊,好像减多了,那么就两两组合,再加上去,加多了就三三组合减回去........
没错,就是容斥原理

具体实现时,质因子分解用快速分解法O(√M)分解,
容斥时我们枚举二进制数进行容斥
搞完啦~
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define fo(i,x,y) for (int i = (x); i <= (y); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 1005,maxm = 100005,INF = 1000000000;

LL N,M;
int fac[maxn],faci = 0;

void Sp(){
	LL e = M;
	for (LL i = 2; i * i <= e; i++){
		if (e % i == 0){
			fac[++faci] = i;
			while (e % i == 0) e /= i;
		}
	}
	if (e - 1) fac[++faci] = e;
}

LL qpow(LL a,LL b){
	LL ans = 1;
	for (; b; b >>= 1, a *= a)
		if (b & 1) ans *= a;
	return ans;
}

LL cal(int s){
	LL mult = 1,pos = 1;
	for (int i = 1; s; i++,s >>= 1){
		if (s & 1){
			mult *= fac[i];
			pos *= -1;
		}
	}
	return qpow(M/mult,N) * pos;
}

void solve(){
	Sp();
	LL tot = qpow(M,N),maxv = ((LL)1 << faci) - 1;
	for (int s = 1; s <= maxv; s++)
		tot += cal(s);
	cout<<tot<<endl;
}

int main()
{
	cin>>N>>M;
	solve();
	return 0;
}

免责声明:文章转载自《[HNOI2002]跳蚤 【容斥】》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇重新整理 .net core 实践篇————网关中的身份签名认证[三十七]git flow常用命令下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

echarts基本应用-更改坐标轴文字样式、轴名称、轴刻度、轴线、轴网格、曲线(折线图)、柱体上面显示值(柱状图),鼠标悬浮提示

让我根据这些天的需要总结一些常用文档。1.axisLabel:{axis text,show:true在xAxis或yAxis根下,textStyle:{color:“#333”,//更改坐标轴文本颜色fontSize:12//更改坐标轴文字大小}}2.grid:{图标到周围区域的距离,包括顶部、左侧、右侧和引导,可以是100%left:“1%”right:...

Json 的日期格式转化(时区标准化)

在JavaScript中,这无疑可以通过初始化Data()对象//converttomsecsinceJan11970localTime=d轻松完成。获取时间();步骤2:接下来,通过Data()对象的getTimezoneOffset()方法//obtainlocalUTCoffsetandconverttomseclocalOffset=d找出本地时间偏...

xcode模拟器不显示键盘解决方案

当我们使用Xcode进行开发时,我们并不总是需要在iPhone上运行代码。有时模拟器可以解决这些问题。但当你使用模拟器时,你会发现,如果你使用模拟器上的键盘在TextFiled中输入信息,这是可以的,但如果你使用键盘输入信息,那么你会发现模拟器上的屏幕将不再显示。这是因为默认情况下,xcode使用计算机键盘作为外部键盘,不会弹出虚拟键盘。...

Dapper系列之一:Dapper的入门(多表批量插入)

Dapper只是一个完全开源的代码文件。您可以在项目中的任何位置实现数据到对象ORM操作,其大小小,速度快。Dapper的优点:1。Dapper是一个轻量级ORM类。该代码是一个SQLMapper.cs文件,编译后通常约为40k dll;2.Dapper,快点,你为什么说得快?因为Dapper的速度接近IDataReader,所以列表的数据比DataTabl...

Systemd简介与使用

Systemd在并行启动中采用了比Upstart更激进的方案。图2显示了systemd的并行启动模式。它允许所有配置的服务同时启动。事实上,大多数使用systemd的现代发行版都与此类似。系统通过配置这些单元来切换和管理服务。...

Nohup后台运行程序

场景:我现在需要跑脚本批量处理一些数据,但是我又不想盯着控制台看这个脚本的输出结果,想把这些输出结果记录到一个日志文件里面方案:可以使用Linux的nohup命令,把进程挂起,后台执行用法:$nohupXXXXXX.sh˃˃/runtime/deletedata.log&运行结果(这个数字是进程号):˃˃[1]13120有时候可能会报一个提示:$no...