BZOJ3930: [CQOI2015]选数

42 篇文章 0 订阅
11 篇文章 0 订阅

差不多是条咸鱼了…………


一开始对着题目yy了一个貌似很正确,复杂度不会算的搜索,想了想不是很敢打,往DP想,然后想出了一个看起来很正确的DP,然后挂了….
那想容斥咯………..不会………
那试试反演咯…………..还是不会………
那我到底会什么…………..
看题解好像还是会的



这题做法好多的样子,主要是两类,一类是反演,Orz PoPoQQQ μ 的前缀和处理窝看不懂…………还有一类是容斥,因为区间里选n个不是全部一样的数,有一个易证的结论:他们的gcd不会超过区间长度,
所以现将区间缩为(l/Kr/K),设f[i]表示区间里选n个不是全部一样的数,gcd是i*K的方案数, N 是可以选择的区间的长度,可以得到一个公式
f[i]=NnNi|jf[j](减 N <script type="math/tex" id="MathJax-Element-442">N</script>是因为要减去全部一样的方案数)
最后要加上全部选一样的数对答案的贡献,那么只有K在可以选择的区间内时才会产生1的贡献



code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

const int maxn = 100010;
const ll Mod = 1e9+7;
ll pw(ll x,int k)
{
    x%=Mod;ll ret=1;
    for(ll t=x;k;k>>=1,t=t*t%Mod)
        if(k&1)ret=ret*t%Mod;
    return ret;
}
ll f[maxn];
int n,K,L,H;

int main()
{
    scanf("%d%d%d%d",&n,&K,&L,&H);
    int l=L/K,r=H/K;
    if(L%K) l++;
    int N=r-l+1;
    for(int i=N;i>=1;i--)
    {
        int tr=r/i,tl=l/i;
        if(l%i)tl++;
        if(tl<=tr)
        {
            f[i]=pw(tr-tl+1,n);
            f[i]-=tr-tl+1;
            for(int j=2*i;j<=N;j+=i) f[i]-=f[j];
            f[i]=(f[i]%Mod+Mod)%Mod;
        }
    }
    if(l<=1&&l<=r) f[1]=(f[1]+1)%Mod;
    printf("%lld\n",f[1]);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值