zoukankan      html  css  js  c++  java
  • CCPC2020绵阳 L题 Lottery

    Pro:
    https://pintia.cn/problem-sets/1322796904464203776/problems/1322798545527595019
    Sol:
    首先可以考虑一个多重背包的二进制拆解
    注意,这里的二进制拆解指的是拆成(O(logn))(2^k)的形式
    实现的话就是先(1,2,4,8,16...)能拆就拆
    对于剩下的部分直接拆成它在二进制下每一位为1的位即可

    然后问题转换成了每个物品个数都不超过2的一个问题

    继而发现
    假设序列形如
    (112121012111.....)
    每一段连续的1和2是独立的!
    因为他们的最大和也不可能超过(2^{(k+1)})
    所以每一段单独dp,把答案乘起来即可。

    #include<bits/stdc++.h>
    #define N 1100000
    #define db double
    #define ll long long
    #define ldb long double
    #define ull unsigned long long
    using namespace std;
    const int h=3,ki=149,mo=1e9+7;
    inline int inc(int x,int k){x+=k;return x<mo?x:x-mo;}
    inline int dec(int x,int k){x-=k;return x>=0?x:x+mo;}
    inline int read()
    {
    	char ch=0;int x=0,flag=1;
    	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
    	return x*flag;
    }
    inline void write(int x)
    {
    	if(!x)return (void)putchar(48);
    	if(x<0)putchar(45),x=-x;
    	int len=0,p[20];
    	while(x)p[++len]=x%10,x/=10;
    	for(int i=len;i>=1;i--)putchar(p[i]+48);
    }
    const db eps=1e-7,inf=1e9+7,pi=acos(-1);
    inline db Read(){db x;scanf("%lf",&x);return x;}
    inline void Write(db x){printf("%lf",x);}
    map<int,int>mp;
    map<int,int>::iterator it;
    int main()
    {
    	int t=read(); 
    	for(int o=1;o<=t;o++)
    	{
    		int n=read(),ans=1;mp.clear();
    		for(int i=1;i<=n;i++){int x=read(),k=read();mp[x]+=k;}
    		
    		for(it=mp.begin();it!=mp.end();it++)
    		{
    			int x=it->first,k=it->second;mp[x]=0;
    			for(int i=0;(1<<i)<=k;i++)mp[x+i]++,k-=(1<<i);
    			for(int i=0;(1<<i)<=k;i++)if((1<<i)&k)mp[x+i]++,k-=(1<<i);
    		}
    		int f0=1,f1=0;
    		for(it=mp.begin();it!=mp.end();it++)
    		{
    			int x=it->first,k=it->second;
    			if(!mp[x-1])ans=1ll*ans*inc(f0,f1)%mo,f0=1,f1=0;
    			f1=(k==1)?f1:inc(f0,f1);f0=inc(f0,f0);
    		}
    		ans=1ll*ans*inc(f0,f1)%mo;
    		printf("Case #%d: %d
    ",o,(ans%mo+mo)%mo);
    	} 
    }
    

    这个题还有另外一个做法
    如下
    但我还不太清楚具体怎么实现(怎么比较当前的和和下一个数字的大小啊qwq)

  • 相关阅读:
    c++爱问的面试问题
    Ognl底层使用
    [勘探开发]成绩,全栈开发,健全&amp;借贷
    FMS4
    Flex远程调用机制RemoteObject应用技巧
    Flex开发框架cairngorm入门实例
    RC1意思
    获取JAVA[WEB]项目相关路径的几种方法
    排序算法
    jQuery Validate
  • 原文地址:https://www.cnblogs.com/Creed-qwq/p/13931375.html
Copyright © 2011-2022 走看看