首页 > 其他分享 >恨7不成妻题解

恨7不成妻题解

时间:2023-10-25 14:00:32浏览次数:34  
标签:取模 10 题解 sum times 不成 平方和 bmod

恨7不成妻 题解

分析

数位 \(DP\)

考虑题目中的两个条件,每一位不等于 \(7\) 直接枚举时把 \(7\) 排除,其他两种情况直接放在状态里。

因为题目要求平方和,我们考虑每次加上一位(设加入的是第 \(i\) 位)时会发生什么

设原平方和为

\[\sum_{k=1}^t a_k^2 \]

加入一位 \(p\) 之后每个数变成 \(a_k+p\times 10^{i-1}\)

现平方和为

\[\begin{matrix} \\&\sum_{k=1}^t (a_k+p\times 10^{i-1})^2 \\=&\sum_{k=1}^t [(p\times 10^{i-1})^2+2a_kp\times 10^{i-1}+a_k^2] \\=&t(p\times 10^{i-1})^2+2p\times 10^{i-1}\sum_{k=1}^ta_k+\sum_{k=1}^ta_k^2 \end{matrix} \]

可以看出一共需要维护三个东西:个数,和,平方和。

设状态 \(f[i,j,k],g[i,j,k],h[i,j,k]\) 为一共有 \(i\) 位,各位和对 \(7\) 取模为 \(j\),这个数对 \(7\) 取模为 \(k\) 的个数,和,平方和。

状态转移方程也很好列出

设 \(b=(j-p)\bmod 7,c=(l-p\times 10^{i-1})\bmod 7,x=p\times10^{i-1}\)

\[f[i,j,k]=\sum_{p=0}^9 f[i-1,b,c]\times[p\ne7] \]

\[g[i,j,k]=\sum_{p=0}^9 (f[i-1,b,c]\times x+g[i-1,b,c])\times[p\ne7] \]

\[h[i,j,k]=\sum_{p=0}^9 (f[i-1,b,c]\times x\times x+g[i-1,b,c]\times x+h[i-1,b,c])\times[p\ne7] \]

然后考虑每一位怎么求

题目要求 \(l\sim r\),我们就可以用 \((0,r+1)\) 的答案减去 \((0,l)\) 的答案(闭区间的原因是不用考虑边界条件),所以先考虑 \((0,r+1)\)。

数位 \(DP\) 套路,先拆位。

然后对于每一位,从高到底枚举填哪个数,对于不是最大值的,直接暴力填累加答案,对于是最大值的直接跳过看下一位。注意枚举每一位的时候不要枚举到 \(7\)。

我们另设三个变量,方便记录之前填的数字。

\(now\) 前面的数字对 \(7\) 取模,\(sum\) 前面的每一位之和对 \(7\) 取模,\(tmp\) 前面的每一位(可先对 \(10^9+7\) 取模。

对于 \(p<a_i\) 的时候。

设 \(b=(7-(sum+p))\bmod 7,c=(7-(now+p\times 10^{i-1}))\bmod 7,x=tmp+p\times10^{i-1}\)

\[ans=ans+\sum_{j=0}^7\sum_{l=0}^7[j\ne b][l\ne c](f[i-1,j,l]\times x\times x+2g[i-1,j,l]\times x+h[i-1,j,l]) \]

注意到第 \(i\) 位的时候如果 \(a_i=7\) 需要直接退出。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
    char ch=getchar();int x=0;bool f=1;
    while(ch<'0'||'9'<ch){if(ch=='-')f=0;ch=getchar();}
    while('0'<=ch&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return f?x:-x;
}
const int mod=1e9+7;
int f[20][7][7],g[20][7][7],h[20][7][7],num[20],ksm[20];
void init(){
    ksm[0]=num[0]=1;for(int i=1;i<=19;i++)num[i]=num[i-1]*10%7,ksm[i]=ksm[i-1]*10%mod;
    f[0][0][0]=1;
    for(int i=1;i<=19;i++)
        for(int j=0;j<7;j++)
            for(int l=0;l<7;l++){
                for(int p=0;p<10;p++)if(p!=7){
                    int a=i-1,b=((j-p)%7+7)%7,c=((l-p*num[i-1])%7+7)%7,x=p*ksm[i-1]%mod;
                    (f[i][j][l]+=f[a][b][c])%=mod;
                    (g[i][j][l]+=f[a][b][c]*x%mod+g[a][b][c])%=mod;
                    (h[i][j][l]+=(f[a][b][c]*x%mod*x%mod+g[a][b][c]*x%mod*2%mod+h[a][b][c])%mod)%=mod;
                }
            }
    return;
}
int len,a[20];
inline int solve(int r){
    len=0;while(r)a[++len]=r%10,r/=10;
    int ans=0,now=0,sum=0,tmp=0;
    for(int i=len;i;i--){
        for(int p=0;p<a[i];p++)if(p!=7){
            int a=i-1,b=(7-(sum+p)%7)%7,c=(7-(now+p*num[i-1])%7)%7,x=(tmp+p*ksm[i-1]%mod)%mod;
            for(int j=0;j<7;j++)
                if(j!=b)
                    for(int l=0;l<7;l++)
                        if(l!=c)
                            (ans+=(f[a][j][l]*x%mod*x%mod+g[a][j][l]*x%mod*2%mod+h[a][j][l])%mod)%=mod;
        }
        if(a[i]==7)break;
        (tmp+=a[i]*ksm[i-1]%mod)%=mod;
        (now+=a[i]*num[i-1]%7)%=7;
        (sum+=a[i])%=7;
    }
    return ans;
}
signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    init();
    int T=read();
    while(T--){
        int l=read(),r=read();
        printf("%lld\n",(mod+solve(r+1)-solve(l))%mod);
    }
    return 0;
}

标签:取模,10,题解,sum,times,不成,平方和,bmod
From: https://www.cnblogs.com/sunzz3183/p/17787064.html

相关文章

  • P9771 HUSTFC 2023 排列排序问题 题解
    Question给出一个\(N\)个元素的排序\(a\),我们可以对排列进行一些操作将这个排列切割成若干个序列将其中一些序列翻转将这些序列连接起来得到一个新的排列需要让最后的排列有序Solution这个题的描述有点小问题理解应该是切一次,然后再反转合并,不可能会先合并再切再反转......
  • P9744 「KDOI-06-S」消除序列 题解
    @目录DesciptionSolutionCodeDesciption给定一个长度为\(i\)的序列\(v_1,v_2,\dots,v_n\),初始时所有元素的值都为\(1\)。对于下标\(i\)有\(3\)种操作:将\(v_1,v_2,\dots,v_i\)的值变为\(0\),费用是\(a_i\)。将\(v_i\)的值变为\(0\),费用是\(b_i\)。将\(v_i\)......
  • Meta Hacker Cup 2023 Round 1 题解
    ProblemA:HereComesSantaClaus给一个数列,要求分成若干组,要求每组至少2个数,使得所有组中位数的最大值与最小值之差尽量大,求这个值。#include<bits/stdc++.h>usingnamespacestd;#defineFor(i,n)for(inti=1;i<=n;i++)#defineFork(i,k,n)for(inti=k;i<=n;i++)#define......
  • pytest运行警告问题解决:DeprecationWarning: pkg_resources is deprecated as an API
    前言最近在运行pytest的时候,经常出现这个警告DeprecationWarning:pkg_resourcesisdeprecatedasanAPISeehttps://setuptools.pypa.io/en/latest/pkg_resources.htmlfrompkg_resourcesimportiter_entry_points从警告上看是方法被弃用,肯定是因为新版弃用了旧版的语法。遇......
  • szfpga Lattice高速下载器HW-USBN-2B 常见问题解答
      .产品特点     1).支持windows7,Windows10操作系统,两个操作系统非常稳定不断线。  2).支持JTAG模式,速度快,最高30Mb/s,调试serdescore,不会像hw-usbn-2a出现错误。如这种错误Error:failedtosetcablepor(cable:USBport:EzUSB-0error:-1)  3). ......
  • CF1854E Games Bundles 题解
    乱搞题设个\(dp[i]\)表示和为\(i\)的子序列个数,那么转移是容易的,\(dp[j]+=dp[j-i]\),然后就判下\(dp[60]+dp[60-i]\)是否大于\(m\),发现这样子搞对于比较大的数可能达不到\(m\)的限制,因为这样子转移,默认的是一个数只选一次,但是我们可以重复选,这启发我们需要设定一个值......
  • 题解 CF903G【Yet Another Maxflow Problem】
    加边\(A_n\stackrel{0}{\to}A_{n+1}\),\(B_0\stackrel{0}{\to}B_1\)。称形如\(A_i\toA_{i+1}\)的边为左部边,形如\(B_j\toB_{j+1}\)的边为右部边,形如\(A_i\toB_j\)的边为中间边。根据最大流最小割定理,将最大流问题转化为最小割问题求解。显然,至少存在一组最小割,包含恰好......
  • CF1777D题解
    分析首先看到那个\(10^{100}\)再加上样例,我们就能意识到在不是特别多的操作次数后这颗树上的值就会全变成\(0\)。因为没有子节点在一次操作后显然就会变成\(0\),然后第一次叶节点就会变成\(0\),然后下一次子节点中只有叶节点的就会变成\(0\),以此类推,理论上最多操作\(n\)......
  • CF1878B题解
    CF1878BAleksaandStack题目翻译给定\(n\),试构造一个长度为\(n\)的严格上升正整数序列\(a_1,a_2,a_3,...,a_n\)使得\(\foralli\in[3,n],(a_{i-1}+a_{i-2})\nmid3a_i\)。单个测试点内包含多组测试数据。思路拿到题目,发现不好一个数一个数地构造,考虑......
  • 华科新生赛题解
    因为学校里面写代码的条件不足,比如教学楼里面使用键盘就会被盯着看。感觉有点点自闭。早知道退学了。不知道现在退学是不是算晚。昨天好兄弟车昱辉说你是在学习又不是在打游戏,但是我还是很羞涩。Abfs,需要把已经搜到的点在枚举1到n的时候去掉,所以可以使用并查集。或者链表......