zoukankan      html  css  js  c++  java
  • 【HDU4507】Seven-数位DP

    测试地址:Seven
    做法: 本题需要用到数位DP。
    是的,我看这题题目名字实在太长,就自己给取了个名字…首先看它给的条件,如果只求数字个数的话,非常明显是数位DP的形式,只需要设num(i,j,k)num(i,j,k)为前ii位中,不卡上界的,数位和对77的余数为jj,数对77的余数为kk的数字的个数,很容易就能转移。而要求数字的和较难一点,但我们也能较快地想出转移。而现在要求数字的平方和,这就有点复杂了。
    然而实际上也不很复杂,你只需要一个结论:一些数的平方和,等于这些数和的平方,减去这些数两两间的乘积之和乘22。这个结论也很容易理解,因为(ai)2=(aiaj)=ai2+ijaiaj(sum a_i)^2=sum (a_isum a_j)=sum a_i^2+sum_{i e j} a_icdot a_j,移项即可得到上面的结论。这样一来,我们需要求f(i,j,k)f(i,j,k),表示满足对应条件(和上面状态定义一样,就不重复写了)的数的和,还有g(i,j,k)g(i,j,k),表示满足对应条件的数两两之间乘积的和。
    我们发现所有转移都可以转化为以下问题:我们有两个集合,分别求出了对应的f,gf,gnumnum,它们合并之后的f,gf,gnumnum怎么求?这个比较好推,就自己推一下就行了,实在不懂就看我代码。还有一个问题是,我们有一个集合,求出了对应的f,gf,gnumnum,那么在这些集合的数之后添加一位数xx后,集合的f,gf,gnumnum怎么变化?这个就稍微复杂一些,以三个数的集合S={a,b,c}S={a,b,c}为例,令新加的位为xx,则:
    (10a+x)+(10b+x)+(10c+x)=10(a+b+c)+3x(10a+x)+(10b+x)+(10c+x)=10(a+b+c)+3x
    (10a+x)(10b+x)+(10b+x)(10c+x)+(10a+x)(10c+x)=100(ab+bc+ac)+20(a+b+c)x+3x2(10a+x)(10b+x)+(10b+x)(10c+x)+(10a+x)(10c+x)=100(ab+bc+ac)+20(a+b+c)x+3x^2
    根据这两个式子我们可以找到规律,首先numnum不变,ff就等于原来的ff1010加上xxnumnum,而gg等于原来的gg100100,加上10(num1)10(num-1)cdot原来的ff,最后加上num(num1)2x2frac{num(num-1)}{2}cdot x^2
    有了这些东西,就可以解决转移的问题了,像模板数位DP一样做就行了。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=1000000007;
    const ll inv2=500000004;
    int T,n;
    ll s[25],num[25][7][7],f[25][7][7],g[25][7][7];
    
    void update(int dgt,int j,int k,ll nowf,ll nowg,ll nownum)
    {
    	g[dgt][j][k]=(g[dgt][j][k]+nowg+nowf*f[dgt][j][k])%mod;
    	f[dgt][j][k]=(f[dgt][j][k]+nowf)%mod;
    	num[dgt][j][k]=(num[dgt][j][k]+nownum)%mod;
    }
    
    ll solve()
    {
    	int nowi=0,nowj=0,nowk=0;
    	ll nowsum=0;
    	memset(f[n+1],0,sizeof(f[n+1]));
    	memset(g[n+1],0,sizeof(g[n+1]));
    	memset(num[n+1],0,sizeof(num[n+1]));
    	for(int dgt=n;dgt>=1;dgt--)
    	{
    		memset(f[dgt],0,sizeof(f[dgt]));
    		memset(g[dgt],0,sizeof(g[dgt]));
    		memset(num[dgt],0,sizeof(num[dgt]));
    		for(int j=0;j<7;j++)
    			for(int k=0;k<7;k++)
    				for(int now=0;now<=9;now++)
    				{
    					if (now==7) continue;
    					int newj=(j+now)%7,newk=(k*10ll+now)%7;
    					ll nowf=(f[dgt+1][j][k]*10ll%mod+now*num[dgt+1][j][k]%mod)%mod;
    					ll nowg=g[dgt+1][j][k]*100ll%mod;
    					nowg=(nowg+f[dgt+1][j][k]*now%mod*10ll%mod*(num[dgt+1][j][k]-1ll+mod)%mod)%mod;
    					nowg=(nowg+num[dgt+1][j][k]*(num[dgt+1][j][k]-1ll)%mod*inv2%mod*now*now%mod)%mod;
    					ll nownum=num[dgt+1][j][k];
    					update(dgt,newj,newk,nowf,nowg,nownum);
    				}
    		
    		if (dgt<n&&(!nowi))
    		{
    			for(int now=0;now<s[dgt];now++)
    			{
    				if (now==7) continue;
    				int newj=(nowj+now)%7,newk=(nowk*10ll+now)%7;
    				update(dgt,newj,newk,(nowsum*10ll+now)%mod,0ll,1ll);
    			}
    		}
    		nowi=(nowi||(s[dgt]==7));
    		nowj=(nowj+s[dgt])%7;
    		nowk=(nowk*10ll+s[dgt])%7;
    		nowsum=(nowsum*10ll+s[dgt])%mod;
    		
    		for(int now=1;now<=((dgt==n)?(s[dgt]-1):9);now++)
    		{
    			if (now==7) continue;
    			update(dgt,now%7,now%7,now,0ll,1ll);
    		}
    	}
    	
    	f[0][0][0]=g[0][0][0]=num[0][0][0]=0;
    	for(int j=1;j<7;j++)
    		for(int k=1;k<7;k++)
    			update(0,0,0,f[1][j][k],g[1][j][k],num[1][j][k]);
    	ll ans=((f[0][0][0]*f[0][0][0]%mod-g[0][0][0]*2ll)%mod+mod)%mod;
    	if ((!nowi)&&nowj&&nowk) ans=(ans+nowsum*nowsum)%mod;
    	return ans;
    }
    
    int main()
    {
    	scanf("%d",&T);
    	while(T--)
    	{
    		ll ans=0,x;
    		
    		scanf("%lld",&x);
    		x--;
    		if (x)
    		{
    			n=0;
    			while(x)
    			{
    				s[++n]=x%10;
    				x/=10;
    			}
    			ans=(mod-solve())%mod;
    		}
    		
    		scanf("%lld",&x);
    		n=0;
    		while(x)
    		{
    			s[++n]=x%10;
    			x/=10;
    		}
    		ans=(ans+solve())%mod;
    		printf("%lld
    ",ans);
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    剖析startup_stm32f407xx.s文件
    我们无法在此设备上激活windows,因为无法连接到你的组织的激活服务器。请确保已连接到你的组织服务器,然后重试。如果仍存在激活问题,请联系组织的支持人员,错误代码:ox80070078
    【DW·智慧海洋(捕鱼作业分析)打卡】task05_模型融合 (简单辨析了一下stacking和blending)
    【DW·智慧海洋(捕鱼作业分析)打卡】task04_模型建立
    【心跳信号分类预测】Datawhale打卡- Task05 模型融合 (尝试记录)
    【心跳信号分类预测】Datawhale打卡- Task4 建模与调参 (贝叶斯搜索调参调包实践)
    【心跳信号分类预测】Datawhale打卡- Task03 特征工程
    【DW·智慧海洋(捕鱼作业分析)打卡】task03_特征工程 (复现top的各种特征工程:分箱特征、网格特征、统计特征、Embedding特征)
    【DW·智慧海洋(捕鱼作业分析)打卡】task02_数据分析 (刺网/围网/拖网)
    【DW·智慧海洋(捕鱼作业分析)打卡】task01_地理数据分析常用工具
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793243.html
Copyright © 2011-2022 走看看