DP进阶
1.数位DP
https://www.luogu.com.cn/problem/P4317
设\(ans_i\)表示\(i\)位为\(1\)的范围内二进制数。
答案就是\(\sum_{i=1}^{log \ n}i^{ans_i}\)快速幂求一下。
然后呢这个\(log \ n=100\)
所以估计是\(O(log^3 \ n)\)
对于每一个\(ans_i\)求法。
考虑数位DP。
设\(DP[i][j]\)表示\(ans_i\)在\(2^j\)内的答案。
\(DP[i][j]=DP[i-1][j-1]+DP[i][j-1]\)
发现\(DP[i][j]=\binom{j}{i}\)
不过这个上界不好处理。
把\(N\)拆成\(2\)进制下\(\sum_{i=1}^{logN}2^i*pig_i(pig_i=0,1)\)
分段来算答案。
要考虑必然\(1\)
凑齐\(3\)个\(logN\)。
快速幂没判0调了一小时
#include <bits/stdc++.h>
using namespace std;
const long long mod=1e7+7;
long long n;
long long c[105][105];
long long ans[105];
long long an=1;
long long qpow(long long x,long long k)
{
if(k==0)return 1;
if(k==1)return x;
long long qq=qpow(x,k/2);
if(k&1)
{
return ((qq*qq)%mod*x)%mod;
}
else
{
return (qq*qq)%mod;
}
}
int main()
{
int i,j,k;
cin>>n;
for(i=0;i<=50;i++)
{
c[i][i]=c[i][0]=1;
}
for(i=2;i<=50;i++)
{
for(j=1;j<i;j++)
{
c[i][j]=c[i-1][j]+c[i-1][j-1];
}
}
k=0;
for(i=50;i>=0;i--)
{
if((n>>i)&1)
{
for(j=1;j<=i;j++)
{
ans[k+j]+=c[i][j];
}
ans[++k]++;
}
}
for(i=1;i<=50;i++)
{
an*=qpow(i,ans[i]);
an%=mod;
}
cout<<an;
return 0;
}
https://www.luogu.com.cn/problem/P6218
这里\(logN=30\)
大可以\(O(N^4)\)
哦跟上题一样,那没事了。
换一种思路。
在\(N<=2*10^9\)下跑暴力需要花\(4\)分钟左右。
也就是说记录下前缀和是不行的,吗?
全部记录是不行的但是只要\(\text{枚举数数}<=10^7\)就是可以的。
那么就可以每隔\(w\)(块长)记录一个前缀和。
达标发程序里。
打表的长度最好要小于\(10^6\)
复杂度是\(O(w)\)
空间复杂度是\(O(\frac{N}{w})\)
这题采用\(w=400000\),因为题解是这样。
分块打表的极限。
\(w=10^7\)
\(N=10^{14}\)
大概。
#include<bits/stdc++.h>
using namespace std;
const int w=4e5;
const int num[5005]={表};
int l,r;
int ll,rr;
int ans,c[2];
int main()
{
int i,j,k;
cin>>l>>r;
ll=(l-1)/w+1;
rr=(r-1)/w+1;
ans=num[rr]-num[ll-1];
for(i=(ll-1)*w+1;i<l;i++)
{
j=i;
c[0]=c[1]=0;
while(j)
{
c[j%2]++;
j/=2;
}
if((c[0]>=c[1]))
{
ans--;
}
}
for(i=r+1;i<=rr*w;i++)
{
j=i;
c[0]=c[1]=0;
while(j)
{
c[j%2]++;
j/=2;
}
if((c[0]>=c[1]))
{
ans--;
}
}
cout<<ans;
return 0;
}
https://www.luogu.com.cn/problem/P4127
卡分块打表。
设\(DP[i]\)表示数字和为\(i\)数被$i整除的数个数。
无法转移。
设\(DP[i][j]\)表示数字和为\(i\)数被\(i\)除余\(j\)数个数。
诶好啊,可以转移了。
然后改成\(DP[i][j][k]\)表示前\(i\)位数字和为\(j\)数被\(j\)除余\(k\)数个数。
\(O(lg^3N)\)常数稍大。

浙公网安备 33010602011771号