HDU 5976 逆元+打表+莫队
来源:互联网 发布:linux vim 向上查找 编辑:程序博客网 时间:2024/05/17 03:58
题意
给一个数,拆分成不同的数,使得乘积最大。
题解
我们可以观察一下如何拆分乘积最大,可以发现从2开始均分。如果最后有剩余的元素,均分到每一个元素1个值,如果还有剩余(只可能剩余1个),分给最后一个元素。
暴力交一发,TLE。
这样的话,我们再次分析这个问题,我们发现拆分后的元素分为两部分(很明显就能看出来),于是这个问题就转化成了区间问题。给你二组区间,问这两组区间的乘积是多少。很明显,莫队可以解决这个问题。
莫队交一发,TLE。
我们再次分析这个问题,我们发现事实上莫队还不够好,我们发现1-1e9这个区间恰好能一次均分的元素个数不超过10^5个,于是我们把10^5个元素算出来,这样的话,我们在莫队转移的时候就多了很多元素可以利用。对于每个查询,我们首先将状态转移到最近的一个均分之后最大元素为当前状态最大元素的状态。然后剔除掉那些不存在的元素。不存在元素的数量是非常少的,我们可以认为剔除过程是O(1)的。这样的话,总体复杂度O(N)。
代码
#include<bits/stdc++.h>#define LL long long#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(t) while(t)#define MEM(a,b) memset(a,b,sizeof(a))#define MAXN 1000010#define BUF 25001000#define MOD 1000000007#define INF 0x3f3f3f3fusing namespace std;LL mp[MAXN];LL multi[MAXN];struct Node { int id,x,alt,art,blt,brt; LL ans;};Node nodes[MAXN];LL exgcd(LL a,LL b,LL &x,LL &y){ if(b==0){ x=1,y=0; return a; } LL ans=exgcd(b,a%b,x,y); LL temp=x; x=y; y=temp-(a/b)*y; return ans;}LL inv(LL a){ LL x,y; LL t=exgcd(a,MOD,x,y); if(t!=1) return -1; return (x%MOD+MOD)%MOD;}int main() {// freopen("d://input.txt","r",stdin);// freopen("d://out1.txt","w",stdout); int sum=0; MEM(mp,0); UP(i,2,100010) { sum+=i; mp[i]=sum; } multi[1]=1; UP(i,2,100010) { multi[i]=(multi[i-1]*i)%MOD; } int t; scanf("%d",&t); UP(i,0,t) { nodes[i].id=i; scanf("%d",&nodes[i].x); if(nodes[i].x<5){ printf("%d\n",nodes[i].x); continue; } int pos=upper_bound(mp,mp+50010,nodes[i].x)-mp-1; nodes[i].alt=nodes[i].art=nodes[i].blt=nodes[i].brt=1; if(nodes[i].x==mp[pos]) { nodes[i].alt=2,nodes[i].art=pos; } else if(nodes[i].x<mp[pos]+pos-1) { nodes[i].alt=2,nodes[i].art=pos-(nodes[i].x-mp[pos]); nodes[i].blt=pos+2-(nodes[i].x-mp[pos]),nodes[i].brt=pos+1; } else if(nodes[i].x==mp[pos]+pos-1) { nodes[i].blt=3,nodes[i].brt=pos+1; } else if(nodes[i].x==mp[pos]+pos) { nodes[i].alt=3,nodes[i].art=pos; nodes[i].blt=pos+2,nodes[i].brt=pos+2; }// cout<<nodes[i].alt<<" "<<nodes[i].art<<" "<<nodes[i].blt<<" "<<nodes[i].brt<<endl; LL ans=multi[max(nodes[i].art,nodes[i].brt)];// cout<<ans<<endl; DOWN(j,nodes[i].blt,nodes[i].art+1) ans=(ans*inv(j))%MOD; DOWN(j,nodes[i].alt,2) ans=(ans*inv(j))%MOD; printf("%I64d\n",ans); }}
阅读全文
0 0
- HDU 5976 逆元+打表+莫队
- hdu 5793A Boring Question (打表 + 乘法逆元 + 快速模)
- 【HDU】3944 - DP?(Lucas & 逆元 & 大组合数 & 打表)
- 大数组合数取模(逆元+打表)
- HDU 5976 逆元
- HDU 5976 Detachment 逆元
- HDU 5976 贪心+逆元
- hdu 2136 打表
- hdu 1061打表
- HDU 1056 打表
- HDU 5867 打表
- HDU 5407 CRB and Candies (2015多校第10场第一题)素数打表,除法取模(乘法逆元)
- HDU 5976 Detachment(逆元)+逆元总结
- UVA1583 - Digit Generator(生成元,打表)
- hdu 5976 Detachment 逆元+二分+数学
- HDU 5976 Detachment (逆元)
- HDU 5976 Detachment (数学规律+逆元)
- 莫队 + 组合 + 逆元 HDU 5145
- 判断是否是在微信的内置浏览器里打开的网页
- 手机号归属地批量判断,106短信群发,1069短信营销,短信推广,公众号商城,号码区分,号码采集
- bzoj1863[Zjoi2006] trouble 皇帝的烦恼(二分+dp)
- LeetCode
- CSS里常见的块级元素和行内元素
- HDU 5976 逆元+打表+莫队
- OpenCV-二值图像连通域分析
- cookie是什么?php中cookie的设置和使用
- adb 常用命令
- angular+豪华版购物车+模糊查询+可以多选删除
- 账户
- SpringBoot学习-项目创建
- 压缩文件注意(rar软件和zip软件区别)
- Hive的四种数据导入方式