51nod方程的解数 1436
题意:
1436 方程的解数
1.0 秒 131,072.0 KB 80 分 5级题
请计算这个方程组有多少合法的整数解,答案比较大,对m取余后输出。对于样例,有三组解{1, 1}, {3, 1}, {1, 3}。
输入
单组测试数据。
第一行包含四个整数 n, k, l, m (2 ≤ n ≤ 10^18, 0 ≤ k ≤ 10^18, 0 ≤ l ≤ 64, 1 ≤ m ≤ 10^9 + 7)。
输出
对于每一组数据输出答案占一行。
输入样例
2 1 2 10
输出样例
3
思路:
(1)看到是位运算,那么我首先是想到了位运算有没有什么性质,或者位运算有没有什么运算规律,但是由于本菜鸡实在是太菜了,不清楚。所以就没了
(2)但是我想到了将k进行二进制分解转换,因此这个想法就接近了正解。
以上就是我的想法,下面看正解到底是什么
(1)将k进行分解,我们可以知道k的有些位上是1,有些是0。
我们观察一下这个式子,如果在某一位上是0,那么相邻的两个数,不可能在这一位上同时为1,设满足不存在相邻1的情况是x,那么满足使k的第i位是1的情况数就是2^n - x。
所以如果k在二进制的0 ~ L 位中,存在p个1和q个0,那么可以知道答案ans = x ^ q * y ^ p
(2)那么x怎么计算呢?当第n位为0,那么前n - 1位要满足“不存在相邻1”;当第n位为1,那么前n - 2位就要满足“不存在相邻1”,那么dp[n] = dp[n - 1] + dp[n - 2]。因为n达到1e18,所以递推是肯定行不通的了,所以需要用矩阵快速幂加速递推。
(3)注意判断无解的情况,当然就是(1 << l) <= k&&l != 64的时候。。l = 64时会发生溢出,就算是unsigned long long ,同样会溢出。
(4)
代码实现:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int maxn = 2e5 + 5;ll n,k,l,m;
struct node{ll x[5][5];
}res;
ll f[maxn];void init(){//初始化res.x[0][0] = res.x[0][1] = res.x[1][0] = 1;res.x[1][1] = 0;
}node mul(node a,node b){//矩阵乘法node tmp;tmp.x[0][0] = 0; tmp.x[0][1] = 0;tmp.x[1][0] = 0; tmp.x[1][1] = 0;for(int i = 0;i < 2;i++){for(int j = 0;j < 2;j++){for(int k = 0;k < 2;k++){tmp.x[i][j] =(tmp.x[i][j] + a.x[i][k] * b.x[k][j]) % m;}}}return tmp;
}node qpow(node a,ll b){//矩阵快速幂node ans;ans.x[0][0] = ans.x[1][1] = 1;ans.x[0][1] = ans.x[1][0] = 0;while(b){if(b & 1) ans = mul(ans,a);b >>= 1;a = mul(a,a);}return ans;
}void ans_cf(node a){f[0] = (a.x[1][0] + a.x[0][0]) % m;f[1] = (a.x[0][1] + a.x[1][1]) % m;
}ll fpow(ll a,ll b){//快速幂ll res = 1;while(b){if(b & 1) res = (res * a) % m;b >>= 1;a = (a * a) % m;}return res % m;
}int main(){scanf("%lld%lld%lld%lld",&n,&k,&l,&m);//输入ull t = 1ull << l;//判断无解的情况if(m == 1||(k >= t&&l != 64)){//64位,连unsigned long long 都会产生溢出cout << 0 << endl;return 0;}init();//初始化斐波那契数列的矩阵node ans = qpow(res,n);//矩阵快速幂ans_cf(ans);ll x = f[0]; ll y = (fpow(2,n) - x + m) % m;ll cnt0 = 0; ll cnt1 = 0;//统计0和1的数量while(k){if(k % 2) cnt1++;else cnt0++;k >>= 1;}cnt0 += l - cnt0 - cnt1;ll re = (fpow(x,cnt0) * fpow(y,cnt1)) % m;//答案printf("%lld\n",re);return 0;
}
51nod方程的解数 1436相关推荐
- poj 1186 方程的解数(线性探测再哈希)
方程的解数 Time Limit: 15000MS Memory Limit: 128000K Total Submissions: 7084 Accepted: 2431 Case Time ...
- [Swust OJ 166]--方程的解数(hash法)
题目链接:http://acm.swust.edu.cn/problem/0166/ Time limit(ms): 5000 Memory limit(kb): 65535 有如下方程组: A1*x ...
- 【深度优先搜索】计蒜客:方程的解数
用dfs解决: 对于每个xi,都有1~m种选择 可以用深度优先搜索 dfs( index , s )表示考虑进行到下标为index的数和为s 因为每个数都可以选1~m,互不影响,所以不用去重,直接 ...
- POJ前面的题目算法思路【转】
1000 A+B Problem 送分题 49% 2005-5-7 1001 Exponentiation 高精度 85% 2005-5-7 1002 487-3279 n/a 90% 2005-5- ...
- POJ 超详细分类
POJ 各题算法 1000 A+B Problem 送分题 49% 2005-5-7 1001 Exponentiation 高精度 ...
- 数学各个研究方向简介
1. 数论 人类从学会计数开始就一直和自然数打交道了,后来由于实践的需要,数的概念进一步扩充,自然数被叫做正整数,而把它们的相反数叫做负整数,介于正整数和负整数中间的中性数叫做0.它们和起来叫做整数. ...
- hdu 1186(搜索+HASH)
方程的解数 Time Limit: 15000MS Memory Limit: 128000K Total Submissions: 7045 Accepted: 2417 Case Time ...
- 最全数学各个分支简介
来源:算法数学俱乐部 编辑 ∑Gemini 数论 人类从学会计数开始就一直和自然数打交道了,后来由于实践的需要,数的概念进一步扩充,自然数被叫做正整数,而把它们的相反数叫做负整数,介于正整数和负整数中 ...
- NOI 题目 试题 目录 信奥 历年
NOI 题目 试题 目录 信奥 历年 NOI 2018 题目 试题 目录 信奥 历年 第一试 2018年7月18日 08:00-13:00 1.归程 return 2.冒泡排序 ...
- ZJOI2017 讲课Day1笔记
额,参考一下大神的笔记.... 地址 http://www.cnblogs.com/ARZhu-NOIpAK/p/6596879.html Day1 2017-3-24 3:34:43 苟-- 富贵 ...
最新文章
- 涨姿势,Java中New一个对象是个怎么样的过程?
- JSON+AJAX 简单实例
- QuartZ Cron表达式详解
- UI5的货币显示格式的逻辑
- Ndarry/Dataframe使用pytorch转为tensor格式
- FSR 是提高性能和视觉效果
- python SQLite 初识
- C#创建一个文本文件简单代码
- java导出乱码_导出文件乱码问题处理(java)
- 校园网环境下的微信同步
- 【PPT】PPT文档导出PDF文件时,去掉右上角时间
- python名片管理系统难点总结_Python 知识要点:名片管理系统 2.0
- window系统node彻底卸载
- python能开发小程序吗_搭建小程序用Python语言可以搭建吗?
- 2022年华为杯中国研究生数学建模竞赛D题思路
- 听说大数据工资很高,是不是很难学?
- hive 保留四位小数
- Scrapy框架入门之爬取虎扑体育的新闻标题
- DFX部署过程中mysql8版本操作改密码
- 跟优秀的人一起共事,你会变得越来越优秀