• [HDU4507]恨7不成妻(数位dp)


    题意

    给定区间[ l , r ]((1 leq l < r leq 1e18)),求在区间中满足下列条件的所有数x的平方和:

    不存在数字7;不是7的倍数;每一位的数字的和也不是7的倍数

    思路

    数位dp

    状态:位置i,数对7取模j,各个位的和对7取模(,是否顶上界)

    下面的代码用记忆化搜索方式实现,从低位向高位递进。

    已知后面i位数满足的平方和,再在前面加入一个数怎么办

    维护后面i位的平方和pow,由((a+i)^2)=(a^2+2ai+i^2),已知(i^2),那么再加上(a^2+2ai)即可,由于要用到'i',所以还要维护后面i位的和sum。另外,由于后i位可能有很多满足条件的数,所以还要维护个数cnt

    转移有很多细节,比之前写的睿(ruo)智数位dp确实难了一些

    Code:

    #include<bits/stdc++.h>
    #define N 25
    using namespace std;
    typedef long long ll;
    const ll mod = 1000000007;
    int T,a[N],sum;
    ll n,m,x,temp[N];
    struct Node
    {
    	ll cnt,sum,po;
    	Node() {cnt=-1;sum=po=0;}
    	Node(ll c,ll s,ll p) : cnt(c),sum(s),po(p) {}
    }f[N][8][8];//无限制lim才能用的记忆化 
    template <class T>
    void read(T &x)
    {
    	char c;int sign=1;
    	while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    	while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48; x*=sign;
    }
    Node dfs(int pos,int wei,int sum,int lim)//在pos填数,位数和,数,顶上界 
    {
    	if(!pos) return wei==0||sum==0 ? Node(0,0,0):Node(1,0,0);
    	if(f[pos][wei][sum].cnt!=-1&&!lim) return f[pos][wei][sum];
    	int mx=lim ? a[pos] : 9;
    	Node now=Node(0,0,0);
    	for(int i=0;i<=mx;++i)//注意细节
    	{
    		if(i==7) continue;
    		Node nxt=dfs(pos-1,(wei+i)%7,(sum*10+i)%7,lim&&(i==mx));
    		now.cnt=(now.cnt+nxt.cnt)%mod;
    		now.sum=(now.sum+(i*temp[pos]%mod*nxt.cnt%mod+nxt.sum)%mod)%mod;
                    //原先的sum+单选i的贡献*后面的cnt(即i的重复次数)+后面的sum
    		now.po=(now.po + nxt.po + i*temp[pos]%mod*i%mod*temp[pos]%mod*nxt.cnt%mod)%mod;
    		now.po=(now.po+2*i*temp[pos]%mod*nxt.sum%mod)%mod;
                    //计算nxt.sum时已经重复过nxt.cnt次所以这一步不用乘nxt.cnt
    	}
    	if(!lim) f[pos][wei][sum]=now;
    	return now;
    }
    ll dp(ll maxx)
    {
    	sum=0; x=maxx;
    	while(x) {a[++sum]=x%10;x/=10;}
    	return dfs(sum,0,0,1).po;
    }
    int main()
    {
    //	freopen("seven.in","r",stdin);
    //	freopen("seven.out","w",stdout);
    	read(T);
    	temp[1]=1LL;
    	for(int i=2;i<=20;++i) temp[i]=temp[i-1]*10%mod;
    	while(T--)
    	{
    		read(n);read(m);
    		printf("%lld
    ",((dp(m)-dp(n-1))%mod+mod)%mod);	
    	}
    	return 0;
    }
    
  • 相关阅读:
    k-means算法
    偏差-方差分解Bias-Variance Decomposition
    常见machine learning模型实现
    Bag-of-words模型、TF-IDF模型
    atomic原子操作
    oc 计算 带括号 式子
    oc 基本语法 类 静态变量 常量
    通过文件头标识判断图片格式
    十大经典排序算法最强总结(含JAVA代码实现)(转)
    JPEG格式 介绍
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11203662.html
Copyright © 2020-2023  润新知