本节题目:数位之间和的关系。一般需要多加一维状态f[i][j][k]:表示长度为i,第一位是i,数位和等于k的数列个数
Seven Segment Display
题意:每个数字都有一个对应的权值,求l~r(十六进制数)之间所有数的所有数字的权值和
预处理数组有点麻烦,f[i][j]表示长度为i,第一个数是j的所有数列的数位之和的总和,f[i][j]=f[i-1][0~15]+j*(长度为i-1的数列个数即pow(16,i-1)).
dp枚举第i位的数字时统计时还要算上last*(长度为i-1的数列的个数pow(16,i-1)).
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=20;
LL f[N][N];
int s[]={6,2,5,5,4,5,6,3,7,6,6,5,4,5,5,4};
int power[20];
LL dp(LL n){
if(n==0) return s[0]*8;
vector<int> nums;
for(int i=1;i<=8;++i){
nums.push_back(n%16);
n/=16;
}
LL res=0,last=0;
for(int i=nums.size()-1;i>=0;--i){
int x=nums[i];
for(int j=0;j<x;++j){
res+=f[i+1][j]+power[i]*last;
}
last+=s[x];
}
res+=last;
return res;
}
int main(){
power[0]=1;
for(int i=1;i<=10;++i) power[i]=power[i-1]*16;
int res=0,p=16;
for(int i=0;i<16;++i) f[1][i]=s[i],res+=s[i];//cout<<res<<endl;
for(int i=2;i<9;++i,p*=16){
for(int j=0;j<16;++j){
f[i][j]=s[j]*p;
for(int k=0;k<16;++k){
f[i][j]+=f[i-1][k];
}
}
}
res=0;
int T;
cin>>T;
while(T--){
LL n,m,t=0xFFFFFFFF;
scanf("%lld%llX",&n,&m);
LL l=m;
LL r=m+n-1;
if(r>t)
cout<<dp(t)+dp(r%(t+1))-(l==0?0:dp(l-1))<<endl;
else cout<<dp(r)-(l==0?0:dp(l-1))<<endl;
}
return 0;
}
1084. 数字游戏 II
由于科协里最近真的很流行数字游戏。
某人又命名了一种取模数,这种数字必须满足各位数字之和 mod N 为 0。
现在大家又要玩游戏了,指定一个整数闭区间 [a.b],问这个区间内有多少个取模数。
输入格式
输入包含多组测试数据,每组数据占一行。
每组数据包含三个整数 a,b,N。
输出格式
对于每个测试数据输出一行结果,表示区间内各位数字和 mod N 为 0 的数的个数。
数据范围
1≤a,b≤2^31?1,
1≤N<100
输入样例:
1 19 9
输出样例:
2
f[i][j][k] 长度为i 第一位是i 数位和%m等于k。注意(少生孩子)多取模!
eg:(a-b+c)%c一样可能小于0 ,应该是((a-b)%c+c)%c
#include<bits/stdc++.h>
using namespace std;
const int N=20,M=110;
int f[N][N][M]; //f[i][j][k] 长度为i 第一位是i 数位和%m等于k
int mod(int x,int p){
return (x%p+p)%p;
}
void init(int m){
memset(f,0,sizeof f);
for(int i=0;i<10;++i) f[1][i][i%m]++;
for(int i=2;i<N;++i){
for(int j=0;j<10;++j){
for(int k=0;k<10;++k){
for(int r=0;r<m;++r){
f[i][j][r]+=f[i-1][k][mod(r-j,m)];
}
}
}
}
}
int dp(int num,int m){
if(num==0) return 1;
vector<int> nums;
while(num) nums.push_back(num%10),num/=10;
int res=0,last=0;
for(int i=nums.size()-1;i>=0;--i){
int x=nums[i];
for(int j=0;j<x;++j){
res+=f[i+1][j][mod(m-last,m)];
}
last+=x;
if(i==0&&last%m==0) res++;
}
return res;
}
int main(){
int l,r,k;
while(cin>>l>>r>>k){
init(k);
cout<<dp(r,k)-dp(l-1,k)<<endl;
}
}
1086. 恨7不成妻
单身!
依然单身!
吉哥依然单身!
DS 级码农吉哥依然单身!
所以,他平生最恨情人节,不管是 214 还是 77,他都讨厌!
吉哥观察了 214 和 77 这两个数,发现:
2+1+4=7
7+7=7×2
77=7×11
最终,他发现原来这一切归根到底都是因为和 7 有关!
所以,他现在甚至讨厌一切和 7 有关的数!
什么样的数和 7 有关呢?
如果一个整数符合下面三个条件之一,那么我们就说这个整数和 7 有关:
整数中某一位是 7;
整数的每一位加起来的和是 7 的整数倍;
这个整数是 7 的整数倍。
现在问题来了:吉哥想知道在一定区间内和 7 无关的整数的平方和。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据占一行,包含两个整数 L 和 R。
输出格式
对于每组数据,请计算 [L,R] 中和 7 无关的数字的平方和,并将结果对 109+7 取模后输出。
数据范围
1≤T≤50,
1≤L≤R≤1018
输入样例:
3
1 9
10 11
17 17
输出样例:
236
221
0
我们要找的数需要满足三个性质,1.不含7 2.数字和%7不等于0 3.数%7不等于0,所以我们的预处理数组需要是个状态f[i][j][a][b]:长度为i,最高位是j,数字之和%7是a,数%7是b。f[i][j][a][b] 由\(f[i-1][0,1,2,3,4,5,6,8,9][a-j*10\)(i-1)\(][b-j]\)转移得到
然后这道题问的是所有数的立方和。假设我们枚举到第i位前面last,当前位枚举位j,那么就是立方和就是\(jA_1^2+jA_2^2+...+jA_t^2=j×10\)i-1\(^2×t+2×j×10\)\(i-1\)\(×(A_1+A_2+...+A_t)+(A_1^2+A_2^2+...+A_t^2)\)
所以需要维护三个值,即\(t=s0=A_1^0+A_2^0+...+A_t^0\),\(s1=A_1^1+A_2^1+...+A_t^1\),\(s2=A_1^2+A_2^2+...+A_t^2\)
\(s0\)直接统计个数即可求,\(s1=jA_1+jA_2+...+jA_t=j×10\)\(i-1\)\(×t+(A_1^1+A_2^1+...+A_t^1)\)
注意(少生孩子)多取模!
#include<bits/stdc++.h>
using namespace std;
const int N=21;
const int P=1e9+7;
#define int long long
typedef long long LL;
struct F{
int s0,s1,s2;
}f[N][N][N][N];
int mod(int x,int y){
return (x%y+y)%y;
}
int power7[N],power9[N];
void init(){
for(int i=0;i<10;++i){
if(i==7) continue;
auto& v =f[1][i][i%7][i%7];
v.s0++;v.s1+=i;v.s2+=i*i%P;
v.s0%=P;v.s1%=P;v.s2%=P;
}
LL power=10;
for(int i=2;i<N;++i,power*=10){
for(int j=0;j<10;++j){
if(j==7) continue;
for(int a=0;a<7;++a){
for(int b=0;b<7;++b){
for(int k=0;k<10;++k){
if(k==7) continue;
auto& v1=f[i][j][a][b],v2=f[i-1][k][mod(a-j*power,7)][mod(b-j,7)];
v1.s0=mod(v1.s0+v2.s0,P);
v1.s1=mod(v1.s1+(v2.s1+j*(power%P)%P*v2.s0%P)%P,P);
v1.s2= mod(v1.s2+(j*j%P*(power%P)%P*(power%P)%P*v2.s0%P
+2*j*(power%P)%P*v2.s1%P
+v2.s2),P);
}
}
}
}
}
power7[0]=power9[0]=1;
for(int i=1;i<N;++i){
power7[i]=power7[i-1]*10%7;
power9[i]=power9[i-1]*10%P;
}
}
F get(int i,int j,int a,int b){
int ss0,ss1,ss2; ss0=ss1=ss2=0;
for(int aa=0;aa<7;++aa){
for(int bb=0;bb<7;++bb){
if(aa==a||bb==b) continue;
ss0+=f[i][j][aa][bb].s0;ss0%=P;
ss1+=f[i][j][aa][bb].s1;ss1%=P;
ss2+=f[i][j][aa][bb].s2;ss2%=P;
}
}//cout<<i<<" "<<j<<" "<<a<<" "<<b<<" "<<" "<<s0<<" "<<s1<<" "<<s2<<endl;
return (F){ss0,ss1,ss2};
}
signed dp(LL t){
if(t==0) return 0;
LL tt=t;
vector<int> nums;
while(tt) nums.push_back(tt%10),tt/=10;
LL last_a=0,last_b=0,res=0;
for(int i=nums.size()-1;i>=0;--i){
int x=nums[i];
for(int j=0;j<x;++j){
if(j==7) continue;
int a=mod(-last_a*power7[i+1],7),b=mod(-last_b,7);
auto it=get(i+1,j,a,b);
int s0=it.s0,s1=it.s1,s2=it.s2;
// cout<<1+i<<" "<<j<<" "<<a<<" "<<b<<" "<<s0<<" "<<s1<<" "<<s2<<" "<<power9[i+1]<<" "<<last_a<<endl;
res=mod(res+((last_a%P)*(power9[i+1]%P)%P*(last_a%P)%P*(power9[i+1]%P)%P*s0%P
+2*(last_a%P)*(power9[i+1]%P)%P*s1%P
+s2),P);
}
if(x==7) break;
last_a=last_a*10+x;
last_b+=x;
if(i==0&&last_b%7&&last_a%7) res=mod(res+((t%P)*(t%P))%P,P);//cout<<t<<" "<<res<<endl;
}
return res%P;
}
signed main(){
init();
int T;
cin>>T;
while(T--){
int a,b;
cin>>a>>b;
cout<<mod(dp(b)-dp(a-1),P)<<endl;
}
return 0;
}
原文地址:https://www.cnblogs.com/jjl0229/p/12660497.html