zoukankan      html  css  js  c++  java
  • 数学拆分问题--贪心与乘法逆元

    题目链接
    题意:给一个x数,可以将他拆成多个整数,并且这些整数互不相同,使得累积和最大,求累积和最大,最后取模1e9+7

    题解:思考:如果将x拆成多个2的话会让答案值最大,然后再拆成三,再拆成4.....以此类推
    要使答案最大可以从2 3 4 5 ....一直枚举下去,然后将剩余的k值对前面的进行遍历累加,当出现某个数a+k没有与之前重复时,这样会保证答案最大

    先预处理出前缀积,然后将符合条件前缀积除去a,乘上a+k
    除法因为出现取模情况,转为乘法逆元
    乘法逆元:

    ll ext_gcd(ll a,ll b,ll &x,ll &y)
    {
    	ll t,d;
    	if(b==0) {x=1;y=0;return a;
    	}
    	d=ext_gcd(b,a%b,x,y);
    	t=x;
    	x=y;
    	y=t-a/b*y;
    	return d;
    }
    ll Invmod(ll a)
    {
    	ll x,y;
    	if(ext_gcd(a,mod,x,y)!=1) return -1;
    	return (x%mod+mod)%mod;
    }
    

    他人题解博客

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define pb push_back
    ll sum[100005];
    ll mult[100005];
    const ll mod = 1e9+7;
    ll ext_gcd(ll a,ll b,ll &x,ll &y)
    {
    	ll t,d;
    	if(b==0) {x=1;y=0;return a;
    	}
    	d=ext_gcd(b,a%b,x,y);
    	t=x;
    	x=y;
    	y=t-a/b*y;
    	return d;
    }
    ll Invmod(ll a)
    {
    	ll x,y;
    	if(ext_gcd(a,mod,x,y)!=1) return -1;
    	return (x%mod+mod)%mod;
    }
    int main()
    {
    	ll x,i;
    	int t;
    	sum[1]=0,mult[1]=1;
    	for(i=2;i<100005;i++)
    	{
    		sum[i]=sum[i-1]+i;
    	}
    	for(i=2;i<100005;i++)
    	{
    		mult[i]=mult[i-1]*i%mod;
    	}
    	scanf("%d",&t);
    	while(t--)
    	{
    		ll k=0,st=0,i=0;
    		scanf("%d",&x);
    		if(x==1){printf("%d
    ",x);continue;
    		}
    		i=upper_bound(sum+1,sum+100005,x)-sum;
    	 	k=x-sum[i-1];
    	  	st=i-1;
    		i=2;
    		while(1)
    		{
    			if(k+i>st)
    			{		
    				break;
    			}
    			i++;
    		}
    		ll ans=(mult[st]*Invmod(i)%mod)*(k+i)%mod;
    		printf("%lld
    ",ans);
    	}
    	return 0;
    } 
    
  • 相关阅读:
    真的要努力了
    实事求是
    要努力了
    新征程,新目标
    真的要放弃了吗
    集中力量 主攻文科
    May the force be with me.
    记录级排名
    Android开发过程中git、repo、adb、grep等指令的使用
    Ubuntu环境变量设置
  • 原文地址:https://www.cnblogs.com/q1076452761/p/8033988.html
Copyright © 2011-2022 走看看