zoukankan      html  css  js  c++  java
  • CQOI2015 选数

    粘题目描述:

    我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案。

    小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究。

    然而他很快发现工作量太大了,于是向你寻求帮助。

    你的任务很简单,小z会告诉你一个整数K,你需要回答他最大公约数刚好为K的选取方案有多少个。由于方案数较大,你只需要输出其除以1000000007的余数即可。

    题解:

    容斥+递推。如果我们在区间[l,r]种任取n个不全相同的数时,他们的gcd一定<=r-l+1(贝祖)。

    然后就很好搞了,l=(l+k-1)/k,h=h/k。

    然后f[ i ]表示合法区间内选n个数不全相同且gcd==i的方案。

    容斥之前是x^n-x,然后逆向处理即可。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MOD 1000000007
    #define N 100050
    #define ll long long
    int n,k,l,h;
    ll f[N];
    ll fastpow(ll x,int y)
    {
        ll ret = 1ll;
        while(y)
        {
            if(y&1)ret=ret*x%MOD;
            x=x*x%MOD;
            y>>=1;
        }
        return ret;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&k,&l,&h);
        l=(l+k-1)/k,h=h/k;
        for(int i=1;i<=(h-l+1);i++)
        {
            int x = (h/i)-((l+i-1)/i)+1;
            f[i]=fastpow(x,n)-x;
        }
        for(int i=(h-l+1);i>=1;i--)
        {
            for(int j=2;i*j<=(h-l+1);j++)
            {
                f[i]=(f[i]-f[i*j]+MOD)%MOD;
            }
        }
        printf("%lld
    ",f[1]+(l==1));
        return 0;
    }
  • 相关阅读:
    多线程 信号量
    sql在不同数据库查询前几条数据
    Office Outlook同步 很奇怪的BUG
    搜索小技巧整理
    想做一个权限管理插件
    ibatis和Castle学习历程
    查找存储过程中的错误位置
    VS2005项目模版丢失解决方案及VS2005项目模版查找原理
    C# 邮件发送接收
    数据库优化整合
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10048188.html
Copyright © 2011-2022 走看看