zoukankan      html  css  js  c++  java
  • 【JZOJ3771】【NOI2015模拟8.15】小 Z 的烦恼【高精度】【数论】

    题目大意:

    题目链接:https://jzoj.net/senior/#main/show/3771
    ZZ最近遇上了大麻烦,他的数学分析挂科了。于是他只好找数分老师求情。
    善良的数分老师答应不挂他,但是要求小ZZ帮助他一起解决一个难题问题是这样的,现在有
    nn个标号为 1n1sim n 的球和mm个盒子,每个球都可以放进且只能放进一个盒子里面,但是要满足如下的规则:

    1. 若把标号为 ii 的球放进了第 jj 个盒子,那么标号为 2i2i 的球一定要在第 j+1j+1 个盒子里面(若 j<mj<m)

    2. 若把标号为 ii 的球放进了第 jj 个盒子,并且 2k=i2k=i,那么标号为 kk 的球一定要在第j1j-1 个盒子里面(若 j>1j>1)

    ZZ 的数分老师想要知道,给定了 nnmm 的时候,第一个盒子最多能放进去多少个球。事实上,他已经推算出了公式,但是需要检验当 nn 趋向于无穷大时是否仍然满足这个公式,因此 nn 可能会非常大。


    思路:

    若第一个盒子放xx,那么接下来的盒子就分别放2x,22x...2m1x2x,2^2x...2^{m-1}x个球。
    那么若可以放置,就必须使2m1xn2^{m-1}xleq n,所以xn÷2m1xleq ndiv 2^{m-1}
    很明显,第一个格子放奇数个球是成立的。因为2x2x无法得到奇数。那么ansans就加上nleq n的所有奇数个数。
    那么还有一部分偶数也是可以放置在第一个格子的。所以只需继续让n÷2mndiv 2^m(注意不是2m12^{m-1}),再统计奇数个数。直到n=0n=0为止。
    需卡常。


    代码:

    /*#pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-fstrict-overflow")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-skip-blocks")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("-fhoist-adjacent-loads")
    #pragma GCC optimize("-frerun-cse-after-loop")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("-funsafe-loop-optimizations")
    #pragma GCC optimize("inline-functions-called-once")
    #pragma GCC optimize("-fdelete-null-pointer-checks")*/
    //以上卡常神器
    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    const int MAXN=1120;
    const int maxint=1000000000;
    int T,len,k;
    char ch[10010];
    ll n[MAXN+1],ans[MAXN+1],m,t,s;
    
    ll write(ll x)
    {
    	if (x>9) write(x/10);
    	putchar(x%10+48);
    }
    
    bool check(ll a[])  //判断n是否为0
    {
    	for (register int i=MAXN;i>=1;i--)
    		if (a[i]) return 0;
    	return 1;
    }
    
    ll cnt()  //计算奇数个数
    {
    	//不超过n的奇数个数就是[(n+1)/2],[]表示向下取整
    	ll a[MAXN+1];
    	memcpy(a,n,sizeof(a));
    	t=1;
    	for (register int i=MAXN;i>=len-3;i--)  //len用来卡常
    	{  //n+1
    		if (!t) break;
    		a[i]+=t;
    		t=a[i]/maxint;
    		a[i]%=maxint;
    		if (i<len&&a[i]) len=i;
    	}
    	t=0;
    	for (register int i=len;i<=MAXN;i++)  //除以2
    	{
    		a[i]+=t;
    		if (a[i]&1) t=maxint;
    			else t=0;
    		a[i]>>=1;
    		if (i==len&&!a[i]) len++;
    	}
    	t=0;
    	for (register int i=MAXN;i>=len-3;i--)  //记录答案
    	{
    		ans[i]+=a[i]+t;
    		t=0;
    		while (ans[i]>=maxint)
    		{
    			t++;
    			ans[i]-=maxint;
    		}
    		if (i<len&&a[i]) len=i;
    	}
    }
    
    void div(ll a[],int x)
    {
    	t=0;
    	for (register int i=len-3;i<=MAXN;i++)
    	{
    		t=t*maxint+a[i];
    		a[i]=t/x;
    		t%=x;
    		if (i==len&&!a[i]) len++;
    	}
    }
    
    int main()
    {
    	scanf("%d",&T);
    	while (T--)
    	{
    		scanf("%s",ch);
    		len=strlen(ch);
    		for (register int i=1;i<=len;i++)
    			n[MAXN-(len-i)/9]=n[MAXN-(len-i)/9]*10+ch[i-1]-48;
    			
    		for (int i=1;i<=MAXN;i++)  //人才卡常法
    			if (n[i])
    			{
    				len=i-1;
    				break;
    			}
    		
    		scanf("%lld",&m);
    		div(n,1<<(m-1));
    		
    		if (check(n))
    		{
    			putchar(48),putchar(10);
    			continue;
    		}
    		
    		while (!check(n))
    		{
    			cnt();
    			div(n,(1<<m));
    		}
    		
    		k=1;
    		while (!ans[k]) k++;
    		write(ans[k]);
    		ans[k]=0;
    		for (k++;k<=MAXN;k++)
    		{
    			if (ans[k]<10) putchar(48);
    			if (ans[k]<100) putchar(48);
    			if (ans[k]<1000) putchar(48);
    			if (ans[k]<10000) putchar(48);
    			if (ans[k]<100000) putchar(48);
    			if (ans[k]<1000000) putchar(48);
    			if (ans[k]<10000000) putchar(48);
    			if (ans[k]<100000000) putchar(48);
    			write(ans[k]);
    			ans[k]=0;
    		}
    		putchar(10);
    	}
    	return 0;
    }
    
  • 相关阅读:
    python3.6中 字典类型和字符串类型互相转换的方法
    "sorted()"中的"Key Functions"
    tuple unpacking
    理解"__repr__"
    Python中的"Special Method"
    abstractmethod
    JavaScript括号中什么什么不加引号什么时候加引号?
    加载网页时速度慢的一些知识点
    Login登录页面的制作流程(摘要)
    JavaScript总结1
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998390.html
Copyright © 2011-2022 走看看