hdu 4507 吉哥系列故事——恨7不成妻

吉哥系列故事——恨7不成妻

Time Limit : 1000/500ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 16   Accepted Submission(s) : 3
Problem Description
  单身!
  依然单身!
  吉哥依然单身!
  DS级码农吉哥依然单身!
  所以,他生平最恨情人节,不管是214还是77,他都讨厌!
  
  吉哥观察了214和77这两个数,发现:
  2+1+4=7
  7+7=7*2
  77=7*11
  最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数!

  什么样的数和7有关呢?

  如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关——
  1、整数中某一位是7;
  2、整数的每一位加起来的和是7的整数倍;
  3、这个整数是7的整数倍;

  现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
 

Input
输入数据的第一行是case数T(1 <= T <= 50),然后接下来的T行表示T个case;每个case在一行内包含两个正整数L, R(1 <= L <= R <= 10^18)。
 

Output
请计算[L,R]中和7无关的数字的平方和,并将结果对10^9 + 7 求模后输出。
 

Sample Input
 
  
3 1 9 10 11 17 17
 

Sample Output
 
  
236 221 0
 
#include <stdio.h>
#include<string>
#include<algorithm>
#include<math.h>
using namespace std;
const long long MOD=1000000007LL;
struct node{
	long long num;
	long long sum;
	long long qsum;
};
node dp[41][33][33];//数位 每位的数 整个数 
long long p[30]; 
int bit[41];
node dfs(int pos,int sta,int sta1,bool limit)
{
	if(pos==-1)
	{
		node a;
		a.num=(sta!=0&&sta1!=0);
		a.sum=0;
		a.qsum=0;
		return a;
	}
	if(dp[pos][sta][sta1].num!=-1&&!limit)
	{
		return dp[pos][sta][sta1];
	}
	int up=limit?bit[pos]:9;
	node ans;	ans.num=0,ans.sum=0,ans.qsum=0;
	int i;
	for(i=0;i<=up;i++)
	{
		if(i==7)continue;
		node temp=dfs(pos-1,(sta+i)%7,(sta1*10+i)%7,limit&&i==up);		
		ans.num+=temp.num;//数量 
		ans.num%=MOD;
		ans.sum+=((i%MOD*p[pos]%MOD*temp.num%MOD+temp.sum)%MOD);//和 
		ans.sum%=MOD;
	 	ans.qsum+=(temp.qsum%MOD+temp.num%MOD*(i%MOD*p[pos]%MOD)%MOD*(i%MOD*p[pos]%MOD)+2*i%MOD*p[pos]%MOD*temp.sum%MOD);
		ans.qsum%=MOD; 
	}
	if(!limit)
	dp[pos][sta][sta1]=ans;
	return ans; 
}
long long solve(long long x)
{
	int cnt=0;
	while(x)
	{
		bit[cnt++]=x%10;
		x/=10;
	}
	return dfs(cnt-1,0,0,1).qsum;
} 
int main(int argc, char *argv[])
{
	 
	p[0]=1;
	for(int i=1;i<30;i++)
	{
		p[i]=(p[i-1]*10)%MOD;
	}
	int t,i,j,k;
	for(i=0;i<41;i++)
		{
			for(j=0;j<33;j++)
			{
				for(k=0;k<33;k++)
				{
					dp[i][j][k].num=-1;
				}
			}
		}
	scanf("%d",&t);
	while(t--)
	{
		long long n,m;
		scanf("%lld %lld",&n,&m);
		 long long ans=solve(m)%MOD;
		ans-=(solve(n-1)%MOD);
		ans=(ans+MOD)%MOD;
		printf("%lld\n",ans);
	}	
	return 0;
}
因为可能会大的数取模后小于小的数取模所以需要(ans+mod),需要维护三个值 之前的符合的数的个数,之前的数的平方和 之前的数的和 然后利用这三个数可以算出加上当前最高位之后的数的平方和

猜你喜欢

转载自blog.csdn.net/com_ice/article/details/80014042