• 【XSY1476】平凡之路 斜率优化DP


    题目大意

      有(n)个格子,一开始你在(1)号格子。每次你只能往编号更大的格子走。从第(i)个格子走到第(j)个格子的代价是(a_i+a_j imes(j-i) imes m)

      (a_i)为与(i)互质且不大于(i)的正整数的个数。

      (nleq 1000000)

    题解

      显然(a_i=varphi(i))

      如果(j<k)(j)(k)优,那么

    [egin{align} f_j+a_j+a_i imes (i-j) imes m&<f_k+a_k+a_i imes (i-k) imes m\ f_j+a_j+a_iim-a_ijm&<f_k+a_k+a_iim-a_ikm\ f_j+a_j-a_ijm&<f_k+a_k-a_ikm\ f_j+a_j-f_k-a_k&<a_ijm-a_ikm\ frac{f_j-f_k+a_j-a_k}{j-k}&>a_im end{align} ]

      这告诉我们要维护一个斜率递增的栈。

      这道题(a_i)不像其他题一样是单调递增的,所以要把下凸壳上所有的点保存下来,每次二分找到最优的点。

      时间复杂度:(O(nlog n))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    #include<cmath>
    #include<functional>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    typedef pair<ll,ll> pll;
    void sort(int &a,int &b)
    {
    	if(a>b)
    		swap(a,b);
    }
    void open(const char *s)
    {
    #ifndef ONLINE_JUDGE
    	char str[100];
    	sprintf(str,"%s.in",s);
    	freopen(str,"r",stdin);
    	sprintf(str,"%s.out",s);
    	freopen(str,"w",stdout);
    #endif
    }
    int rd()
    {
    	int s=0,c;
    	while((c=getchar())<'0'||c>'9');
    	do
    	{
    		s=s*10+c-'0';
    	}
    	while((c=getchar())>='0'&&c<='9');
    	return s;
    }
    int upmin(int &a,int b)
    {
    	if(b<a)
    	{
    		a=b;
    		return 1;
    	}
    	return 0;
    }
    int upmax(int &a,int b)
    {
    	if(b>a)
    	{
    		a=b;
    		return 1;
    	}
    	return 0;
    }
    int b[1000010];
    int pri[1000010];
    int cnt;
    int phi[1000010];
    ll f[1000010];
    //ll g[1000010];
    int q[1000010];
    //int from[1000010];
    ll gety(int x)
    {
    	return f[x]+phi[x];
    }
    int n,m;
    ll calc(int x,int y)
    {
    	return f[x]+phi[x]+phi[y]*ll(y-x)*m;
    }
    int main()
    {
    	open("pfzr");
    	scanf("%d%d",&n,&m);
    	int i,j;
    	phi[1]=1;
    	for(i=2;i<=n;i++)
    	{
    		if(!b[i])
    		{
    			pri[++cnt]=i;
    			phi[i]=i-1;
    		}
    		for(j=1;j<=cnt&&i*pri[j]<=n;j++)
    		{
    			b[i*pri[j]]=1;
    			if(i%pri[j]==0)
    			{
    				phi[i*pri[j]]=phi[i]*pri[j];
    				break;
    			}
    			phi[i*pri[j]]=phi[i]*phi[pri[j]];
    		}
    	}
    	memset(f,0x7f,sizeof f);
    //	memset(g,0x7f,sizeof g);
    //	g[1]=0;
    	f[1]=0;
    //	for(i=2;i<=n;i++)
    //		for(j=1;j<i;j++)
    //			if(g[j]+phi[j]+ll(phi[i])*(i-j)*m<g[i])
    //			{
    //				g[i]=g[j]+phi[j]+ll(phi[i])*(i-j)*m;
    //				from[i]=j;
    //			}
    	int t=0;
    	q[++t]=1;
    	for(i=2;i<=n;i++)
    	{
    		int l=1,r=t;
    		while(l<r)
    		{
    			int mid=(l+r)>>1;
    			if(gety(q[mid])-gety(q[mid+1])<ll(q[mid]-q[mid+1])*phi[i]*m)
    				r=mid;
    			else
    				l=mid+1;
    		}
    		f[i]=f[q[l]]+phi[q[l]]+ll(phi[i])*(i-q[l])*m;
    		while(t>=2&&(gety(q[t-1])-gety(q[t]))*(q[t]-i)>(gety(q[t])-gety(i))*(q[t-1]-q[t]))
    			t--;
    		while(t>=1&&gety(q[t])-gety(i)>0)
    			t--;
    		q[++t]=i;
    	}
    	printf("%lld
    ",f[n]);
    	return 0;
    }
    
  • 相关阅读:
    Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml)
    Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml)
    Solr 6.7学习笔记(03)-- 样例配置文件 solrconfig.xml
    《深入理解Java虚拟机》笔记04 -- 并发锁
    6.Python3标准库--数学运算
    7.Python3标准库--文件系统
    8.Python3标准库--数据持久存储与交换
    9.Python3标准库--数据压缩与归档
    10.python3标准库--加密
    11.python3标准库--使用进程、线程和协程提供并发性
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8513389.html
Copyright © 2020-2023  润新知