sloj #P4001. 约数个数
题目描述
给出整数x,求它的约数个数
为了加大难度,有m次询问,将每次询问的答案求和然后mod109+7
输入格式
第一行是一个整数m
第二行是整数q1,a,b,c
q1表示第一次询问的数字
第i次询问qi=(qi−1∗a+b)%c
输出格式
所有询问的答案之和mod109+7
样例
输入数据 1
2
2 2 1 9
输出数据 1
4
数据规模与约定
100%的数据保证 A,B,C<=107,1<=Q1<=C。
要做这道题,首先你得知道:n = p1c1*p2c2*p3c3*……*pici这些应该都知道吧,就是质(只)因式分解我是小黑子,不知道的可以出门左转了
还要知道:d(因数个数) = (c1+1)*(c2+1)*(c3+1)*……*(ci+1)
上面那俩都是小学奥数吧,不会的可以让你妈再生一个了,这号基本练废了
证明我就不在这里放出了,这很显然嘛
设e[i]表示最小质(只)因子出现次数,g[i]为约数个数,因为线性筛只用得到最小质(只)因子,对于素数,明显有g[i] = 2,e[i] = 1
如果是合数,那么就有e[k] = e[i]+1; g[k] = (g[i]/(e[i]+1)*(e[k]+1));
e[k]为当前最小质因子出现次数
g[i]需要先除一个e[i]+1则是因为变更这个最小质因子时要把原来算的先给除去才能得到正确答案
不然就是会变为个d = (c1+1)*(c2+1)*(c3+1)*……(ci+1)*((ci+1)+1)
如果还没看懂那就直接抄代码去吧,绝对不是我讲不清楚了
注意:如果这个质因子第一次出现则是个g[k] = g[i]*2
分析完毕,上代码
#include<bits/stdc++.h> #define ll long long #define mod 1000000007 using namespace std; int q,a,b,c,m,g[10000010],e[10000010],vis[10000010],prime[10000010],cnt; ll ans = 0; void pre(){ g[1] = 1; for(int i = 2;i<=c;i++){ if(!vis[i]){ prime[++cnt] = i; e[i] = 1; g[i] = 2; } for(int j = 1;j<=cnt&&i*prime[j]<=c;j++){ int k = i*prime[j]; vis[k] = 1; if(i%prime[j]==0){ e[k] = e[i]+1; g[k] = (g[i]/(e[i]+1)*(e[k]+1)); break; } e[k] = 1; g[k] = g[i]*2; } } } int main(){ scanf("%d%d%d%d%d",&m,&q,&a,&b,&c); pre(); ans = g[q]%mod; for(int i = 2;i<=m;i++){ q = ((long long)q*a+b)%c; ans+=g[q]%mod; } printf("%lld",ans); return 0; }
标签:约数,10000010,ci,询问,个数,因子 From: https://www.cnblogs.com/cztq/p/16945647.html