zoukankan      html  css  js  c++  java
  • [JZOJ2700] 【GDKOI2012模拟02.01】数字

    题目

    在这里插入图片描述

    题目大意

    其实这题的题目大意非常简练,所以我认为我不用解释了。


    思考历程

    首先乱推了一波,然后什么东西都没有发现。
    于是想想D(i)D(i)的性质。
    我发现,由于每次是将各位上的数字相加。所以最多操作三次。
    本来是一个很大的数,然后缩小成百位数,然后缩成十位数,最后缩成个位数。
    我想,既然缩小一次就成了百位数了,所以,为什么不直接把百位数的表打出来,然后再继续推式子呢?
    然后我就把表打了出来。
    于是我就发现,我前面的想法尽是没用的……
    因为我发现了一个显而易见的规律:D(i)=(i1)mod  9+1D(i)=(i-1) mod 9+1
    这个规律可以感性理解,也可以理性证明,反正很简单,我就不说了。
    所以说,一个“被喜欢的数”就是能被x((x1)mod  9+1)x*((x-1)mod 9+1)表示的数。
    接下来就开始了我的瞎搞历程(提醒一下,正确性有误……)
    由于D(x)<=9D(x)<=9,不妨枚举D(x)D(x),设为jj
    设现在的数为ii。显然,如果要成立,首先要满足imod  j=0i mod j=0
    然后乱推:(ij1)mod  9+1=jleft(frac{i}{j}-1 ight) mod 9+1 =j
    所以(ij1)mod  9=j1left(frac{i}{j}-1 ight) mod 9=j-1
    由于j1<9j-1< 9,所以ij1j1(mod  9)frac{i}{j}-1 equiv j-1 (mod 9),所以ijj(mod  9)frac{i}{j} equiv j (mod 9)
    然后就是最尴尬的步骤:ij2(mod  9)iequiv j^2(mod 9)
    所以说,如果ii满足条件,必定有一个jj使得imod  j=0i mod j=0ij2(mod  9)iequiv j^2(mod 9)
    哈,这东西好像可以DP!
    fi,j,kf_{i,j,k}表示到第ii位,模25202520的余数为jj,第ii位上的值为kk的数的个数。
    252025201199的最小公倍数)
    按照之前推出来的条件,我们可以发现它是否为“被喜欢的数”只和jj有关。
    那我就可以愉快地数位DP了。

    然而现实是残酷的……
    WA了……
    后来推了好久,我发现原来是上面的一步出现了问题:
    我们知道ijj(mod  9)frac{i}{j} equiv j (mod 9),可以推出ij2(mod  9)iequiv j^2(mod 9)。可是后者不一定推出前者。
    因为99不是质数……
    不过如果只有这点错误,随便改一改那似乎也是可以过得去的。
    然后我就发现原来还是需要判重!
    怎么判?数位DP怎么判?判不了啊!

    XC说,今天除了第一题之外,其他的题还是很有难度的。
    除了第一题!!!!!!


    正解

    先说一个别人家的正解(当然我不懂是为什么):
    就是打一波表,然后发现,咦,原来是有循环节的!
    然后就随随便便的搞定了……

    然后再说一个正经一些的做法:
    首先对于一个数xD(x)x*D(x),我们可以将其表示为(9t+D(x))D(x)(9t+D(x))*D(x)
    D(x)D(x)的取值是很少的,也就只有99种。
    我们把它当成常数来看,然后就变成9D(x)t+D2(x)9D(x)*t+D^2(x),变成at+bat+b的形式。
    对于一个D(x)D(x),我们可以很容易地计算出它在某一个区间里的贡献。
    然后我们要去重。
    如何去重?容斥原理,将一些式子合并一下就可以了。用扩展中国剩余定理就好。
    可以手打扩展中国剩余定理,其实也是可以推出来的嘛……
    可是某些机智懒惰的同学发现了一个好方法:
    我们将所有的D(x)D(x)的式子列出来,然后将它们都模99
    然后就会惊奇地发现下面的这张表:
    1 4 0 7 7 0 4 1 0
    只有模数相同的有可能可以合并。
    所以运算量大大减少……
    然后我就全部手推出来了。具体见程序(有的式子合并之后无解,我也有注释)。
    然后这题就愉快地解决了。


    代码

    using namespace std;
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    struct func{
    	int a,b,ty;
    } d[20];
    int cnt;
    inline long long getans(long long lim){
    	long long res=0;
    	for (int i=1;i<=cnt;++i)
    		if (lim-d[i].b>=0)
    			res+=((lim-d[i].b)/d[i].a+1)*d[i].ty;//计算贡献……不用解释
    	return res;
    }
    int main(){
    	for (int i=1;i<=9;++i)
    		d[++cnt]={i*9,i*i,1};
    	d[++cnt]={72,64,-1};//d[1] and d[8]
    	d[++cnt]={126,112,-1};//d[2] and d[7]
    	d[++cnt]={180,160,-1};//d[4] and d[5]
    	d[++cnt]={54,36,-1};//d[3] and d[6] 其实在仔细观察之后可以发现,这个和d[6]抵消了。
    	//d[3] and d[9]=empty
    	//d[6] and d[9]=empty
    	//d[3] and d[6] and d[9]=empty
    	int T;
    	scanf("%d",&T);
    	while (T--){
    		long long l,r;
    		scanf("%lld%lld",&l,&r);
    		printf("%lld
    ",getans(r)-getans(l-1));
    	}
    	return 0;
    }
    

    总结

    每次做比赛时,我要么是不屑于打表,要么就是懒得打表。
    可是经验和事实告诉我们,打表是信息学竞赛选手必备的技能!
    我们要培养起自己的打表精神,让它贯彻入信息学竞赛中!
    瞎BB结束

  • 相关阅读:
    A “word-wrap” functionality(一个字符串包裹函数)
    First Unique Character in a String 的变种问题返回第一个找到符合条件的字符
    北美一工作搜索引擎公司技术岗面经
    一房地产数据服务初创公司的面经
    Prime numbers from 1 to 100 (打印 100 以内的素数)
    dubbo面试题(1)
    maven工具日常开发常用命令
    BaseMapper和继承
    《计算机是怎样跑起来的》读书笔记(2)
    AEAP工作总结模板套路
  • 原文地址:https://www.cnblogs.com/jz-597/p/11145249.html
Copyright © 2011-2022 走看看