题目意思非常明确,就是叫你求第n项,据我们学校一个大佬说他推出了矩阵,但是我是菜鸡,那么肯定是用简单的方法水过啦!我们先p^(1/2)的复杂度处理出i=[i,p]范围内的所有种类的(int)(p/i),然后我们就可以知道种可能的除数的范围,就是分成几块
这里我不太会表达,看代码比较好
/**
求n/i的所有结果
**/
#include<stdio.h>
int main( ){
int n;
scanf("%d", &n);
long long nex;
for(long long i=; i<=n; i=nex+){
nex=n/(n/i);
printf("%I64d, %I64d\n", n/i, nex);
/**
n/i保存到数组里从小到大排序,你们就知道块是按这个分的了
**/
/**
看一下输出之类的应该能发现就是类似于
int n;
vector<int> V;
scanf("%d", &n);
for(int i=1; i<=n; ++i){
V.push_back((n/i));
}
......数组去重
会发现这就是n/i的所有结果 **/
}
}
对这些分出来的块我们判断一下,如果两块之间距离很小,那么就没必要用杜教板子推第n项;直接暴力;
其他的就加入该块的前几个元素去推;
具体看恶心的代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define pb push_back
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=;
ll powmod(ll a,ll b) {ll res=;a%=mod; assert(b>=); for(;b;b>>=){if(b&)res=res*a%mod;a=a*a%mod;}return res;}
int _, n;
namespace linear_seq {
const int N=;
ll res[N],base[N],_c[N],_md[N];
vector<int> Md;
void mul(ll *a,ll *b,int k) {
rep(i,,k+k) _c[i]=;
rep(i,,k) if (a[i]) rep(j,,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
for (int i=k+k-;i>=k;i--) if (_c[i])
rep(j,,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
rep(i,,k) a[i]=_c[i];
}
int solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
// printf("%d\n",SZ(b));
ll ans=,pnt=;
int k=SZ(a);
assert(SZ(a)==SZ(b));
rep(i,,k) _md[k--i]=-a[i];_md[k]=;
Md.clear();
rep(i,,k) if (_md[i]!=) Md.push_back(i);
rep(i,,k) res[i]=base[i]=;
res[]=;
while ((1ll<<pnt)<=n) pnt++;
for (int p=pnt;p>=;p--) {
mul(res,res,k);
if ((n>>p)&) {
for (int i=k-;i>=;i--) res[i+]=res[i];res[]=;
rep(j,,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
}
}
rep(i,,k) ans=(ans+res[i]*b[i])%mod;
if (ans<) ans+=mod;
return ans;
}
VI BM(VI s) {
VI C(,),B(,);
int L=,m=,b=;
rep(n,,SZ(s)) {
ll d=;
rep(i,,L+) d=(d+(ll)C[i]*s[n-i])%mod;
if (d==) ++m;
else if (*L<=n) {
VI T=C;
ll c=mod-d*powmod(b,mod-)%mod;
while (SZ(C)<SZ(B)+m) C.pb();
rep(i,,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
L=n+-L; B=T; b=d; m=;
} else {
ll c=mod-d*powmod(b,mod-)%mod;
while (SZ(C)<SZ(B)+m) C.pb();
rep(i,,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
++m;
}
}
return C;
}
int gao(VI a,ll n) {
VI c=BM(a);
c.erase(c.begin());
rep(i,,SZ(c)) c[i]=(mod-c[i])%mod;
return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
}
};
ll sav[], ans[];
int main(){
int T;
register int i, j;
ll c, d, p, num, nex, top, a, b;
scanf("%d", &T);
while(T--){
vector<int> v;
scanf("%I64d%I64d%I64d%I64d%I64d%I64d", &ans[], &ans[], &c, &d, &p, &num);
a=ans[];
b=ans[];
top=;
if(num<){
if(num<=){
printf("%I64d\n", ans[num]);
continue;
}
for(i=; i<=num; ++i){
ans[]=(c*ans[]%mod+d*ans[]%mod+(p/i))%mod;
ans[]=ans[];
ans[]=ans[];
}
printf("%I64d\n", ans[]);
continue;
}
for(i=; i<=p; i=nex+){
nex=p/(p/i);
sav[top++]=(p/i);
}
for(i=; i<=top/; ++i){
swap(sav[i], sav[top-i-]);
}
sav[top]=num;
ans[]=(c*ans[]%mod+d*ans[]%mod+(p/))%mod;///这里处理是因为,在区间[sav[i], sav[i+1]]内sav[i]和[sav[i]+1, sav[i+1]]对p的除数是不同的;所以说第一次处理一下sav[i],就可以让区间变成(sav[i], sav[i+1]]半开半闭区间
ans[]=ans[];
ans[]=ans[];
for(i=; i<top; ++i){
if(sav[i+]>=num){
if(num-sav[i]<=){
for(j=sav[i]+; j<=num; ++j){
ans[]=(c*ans[]%mod+d*ans[]%mod+(p/j))%mod;
ans[]=ans[];
ans[]=ans[];
}
printf("%I64d\n", ans[]);
break;
}else{
v.clear();
for(j=sav[i]+; j<=sav[i]+; ++j){
ans[]=(c*ans[]%mod+d*ans[]%mod+(p/j))%mod;
v.push_back((int)ans[]);
ans[]=ans[];
ans[]=ans[];
}
n=num-sav[i];
printf("%d\n", linear_seq::gao(v, n-));
break;
}
}else if(sav[i+]-sav[i]<=){
for(j=sav[i]+; j<=sav[i+]; ++j){
ans[]=(c*ans[]%mod+d*ans[]%mod+(p/j))%mod;
ans[]=ans[];
ans[]=ans[];
}
}else{
v.clear();
for(j=sav[i]+; j<=sav[i]+; ++j){
ans[]=(c*ans[]%mod+d*ans[]%mod+(p/j))%mod;
v.push_back((int)ans[]);
ans[]=ans[];
ans[]=ans[];
}
n=sav[i+]-sav[i];
ans[]=linear_seq::gao(v, n-);///这里还不是结束,也就是要至少保留连续的两项
ans[]=linear_seq::gao(v, n-);
}
}
}
}
代码