Codeforces Round #426 (Div. 2) C. The Meaningless Game 思维 D. The Bakery dp

题目:http://codeforces.com/contest/834/problem/C

题意:两个人玩游戏, 两个人初始值都为1,每次可以选一个正整数,一个人乘以这个正整数的平方,一个人乘以这个正整数,给你多对数<a,b>,判断会不会出现这个游戏局面

把ab乘起来,判断是不是一个数的三次方,并且是不是能被a和b整除

k^3==a*b&&a%k==0&&b%k==0

结果找k的二分写错了。。。。。。。改了半天,,还好过了

举个会出现的游戏局面的例子

a=a1      *  a2      *   a3^3   *  a4       = (a1*a2*a3*a4) *  a3

b=a1^2  * a2^2  *   a3       *  a4^2   =   (a1*a2*a3*a4)  * (a1*a2*a4)

其中(a1*a2*a3*a4) 也就是k

#include<bits/stdc++.h>
#define eps 1e-9
#define PI 3.141592653589793
#define bs 1000000007
#define bsize 256
#define MEM(a) memset(a,0,sizeof(a))
typedef long long ll;
using namespace std;
int ask(long long x)
{
	long long le=1,ri=1e6;
	long long mid;
	while(le<ri)
	{
		mid=(le+ri)>>1;
		long long now=mid*mid*mid;
		if(now==x)
		return mid;
		else if(le*le*le==x)
		return le;
		else if(ri*ri*ri==x)
		return ri;
		else if(now<x)
		le=mid+1;
		else
		ri=mid;
	}
	return 0;
	
}
int main()
{
	int n;
	long long a,b;
	cin>>n;
	while(n--)
	{
		scanf("%lld %lld",&a,&b);
		long long now=ask(a*b);
		if(now)
		{
			if(a%now==0&&b%now==0)
			printf("Yes\n");
			else
			printf("No\n");
		}
		else
		printf("No\n");
	 } 
	 return 0;
 }
其实有个库函数可以用,cbrt()


D:http://codeforces.com/contest/834/problem/D

题意:给一段序列,分成k个段连续的序列,每段序列的值为这段序列不同的数的个数,求最大的k个序列值的和

做法参考自:http://blog.csdn.net/ssimple_y/article/details/76410328

dp加线段树优化,dp【i】【j】表示前i个数字分成j个部分得到的最大的和

dp【i】【j】=max(dp【t】【j-1】+dif【t+1】【i】)dif【i】【i】表示i到j段不同数字的个数,正常转移会t

这里用线段树优化,具体看代码

#include<bits/stdc++.h>
using namespace std;
int n,k,cot=0;
const int maxn=40000;
int a[maxn],book[maxn],pre[maxn],lazy[4*maxn],seg[4*maxn];
int dp[maxn][55];
void pushback(int node)
{
    seg[node]=max(seg[node<<1],seg[node<<1|1]);
    return ;
}
void pushdown(int node)
{
    if(lazy[node])
    {
        seg[node<<1]+=lazy[node];
        lazy[node<<1]+=lazy[node];
        seg[node<<1|1]+=lazy[node];
        lazy[node<<1|1]+=lazy[node];
        lazy[node]=0;
    }
    return ;
}
void update(int le,int ri,int k,int l,int r,int node)
{
    if(le<=l&&ri>=r)
    {
        seg[node]+=k;
        lazy[node]+=k;
        return ;
    }
    pushdown(node);
    int m=(l+r)>>1;
    if(m>=le)
    update(le,ri,k,l,m,node<<1);
    if(ri>m)
    update(le,ri,k,m+1,r,node<<1|1);
    pushback(node);
    return ;
}
int query(int le,int ri,int l,int r,int node)
{
    if(le<=l&&ri>=r)
    {
        return seg[node];
    }
    pushdown(node);
    int m=(l+r)>>1;
    int ans=0;
    if(m>=le)
    ans=max(query(le,ri,l,m,node<<1),ans);
    if(m<ri)
    ans=max(query(le,ri,m+1,r,node<<1|1),ans);
  //  pushback(node);
    return ans;
}
int main()
{
    cin>>n>>k;
    int i,j;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        pre[i]=book[a[i]];//记录相同的数最后一次出现的位置保证了相同的数只能对一个位置加一次
        book[a[i]]=i;
    }
    for(i=1;i<=k;i++)
    {
        memset(seg,0,sizeof(seg));
        memset(lazy,0,sizeof(lazy));
        for(j=1;j<=n;j++)
        {
            update(j,j,dp[j][i-1],0,n,1);//先给节点加上一个dp【t】【j-1】的初值
        }
        for(j=i;j<=n;j++)
        {
            update(max(i-1,pre[j]),j-1,1,0,n,1);//dif【t+1】【i】这部分并不好直接求,直接加,所以可以反向考虑,
            dp[j][i]=query(i-1,j-1,0,n,1);
        }
    }
    cout<<dp[n][k]<<endl;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值