• [HNOI2002] 跳蚤


    题目描述

    Z城市居住着很多只跳蚤。在Z城市周六生活频道有一个娱乐节目。一只跳蚤将被请上一个高空钢丝的正中央。钢丝很长,可以看作是无限长。节目主持人会给该跳蚤发一张卡片。卡片上写有N+1个自然数。其中最后一个是M,而前N个数都不超过M,卡片上允许有相同的数字。跳蚤每次可以从卡片上任意选择一个自然数S,然后向左,或向右跳S个单位长度。而他最终的任务是跳到距离他左边一个单位长度的地方,并捡起位于那里的礼物。

    比如当N=2,M=18时,持有卡片(10, 15, 18)的跳蚤,就可以完成任务:他可以先向左跳10个单位长度,然后再连向左跳3次,每次15个单位长度,最后再向右连跳3次,每次18个单位长度。而持有卡片(12, 15, 18)的跳蚤,则怎么也不可能跳到距他左边一个单位长度的地方。

    当确定N和M后,显然一共有(M^N)张不同的卡片。现在的问题是,在这所有的卡片中,有多少张可以完成任务。

    输入输出格式

    输入格式:

    输入文件有且仅有一行,包括用空格分开的两个整数N和M。

    输出格式:

    输出文件有且仅有一行,即可以完成任务的卡片数。

    (1≤N≤M≤10^{8}) ,且 (MN≤10^{16})

    输入输出样例

    输入样例#1:

    2 4

    输出样例#1:

    12

    说明

    这12张卡片分别是:

    (1, 1, 4), (1, 2, 4), (1, 3, 4), (1, 4, 4), (2, 1, 4), (2, 3, 4),

    (3, 1, 4), (3, 2, 4), (3, 3, 4), (3, 4, 4), (4, 1, 4), (4, 3, 4)

    题解

    有m种卡片,卡片上的数字可以使用无数次,使得最后的坐标在原点-1那么就可以看成
    (a*x_1+b*x_2+c*x_3+...+m*x_{n+1}=1),其中(x_{n+1})=M 那么也就可以推出
    (GCD(x_1,x_2,x_3...x_{n+1})=1) ,也就是这n+1个元素都互质
    那么我们的初始答案就是ans=(M^n),然后减去这些数中公约数的方案

    那么我们可以枚举1~m中m的因子,那么就有m/t个t的倍数,把数列中全都是这些m/t个数的方案数减去即可
    但是这种方法时候有问题的,我们可能会减去多次同种方案

    那么我们就可以用容斥原理求出答案
    ans=(m^n)-(有公因数2的n元组)-(有公因数3的n元组)-(有公因数5的n元组)+(有公因数2,3的n元组)+(有公因数2,5的n元组)+(有公因数3,5的n元组)-(有公因数2,3,5的n元组)+...

    code

    #include<bits/stdc++.h>
    #define in(i) (i=read())
    using namespace std;
    typedef long long lol;
    lol read() {
        lol ans=0,f=1; char i=getchar();
        while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
        while(i>='0' && i<='9') {ans=(ans<<1)+(ans<<3)+i-'0'; i=getchar();}
        return ans*f;
    }
    lol n,m,ans,cnt;
    lol p[1000010];
    lol qpow(lol a,lol x) {
        lol ans=1;
        while(x) {
            if(x&1) ans*=a;
            x>>=1;
            a*=a;
        }
        return ans;
    }
    void divide(lol m) {
        for(lol i=2;i*i<=m;i++) {
            if(m%i==0) {
                p[++cnt]=i;
                while(m%i==0) m/=i;
            }
        }
        if(m>1) p[++cnt]=m;
    }
    void dfs(lol x,lol sum,lol step) {
        if(x>cnt) {
            if(!step) return;
            if(step&1) ans-=qpow(m/sum,n);
            else ans+=qpow(m/sum,n);
            return;
        }
        dfs(x+1,sum,step);
        dfs(x+1,sum*p[x],step+1);
    }
    int main()
    {
        in(n); in(m);
        ans=qpow(m,n); divide(m);
        dfs(1,1,0);
        cout<<ans<<endl;
    }
    

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    VS2015调试ArcMap Add-in插件提示尝试运行项目时出错,无法启动程序“路径arcmap.exe”
    c#重命名文件,报错“System.NotSupportedException”类型的未经处理的异常在 mscorlib.dll 中发生”
    C# string contains 不区分大小写
    CSS div 高度满屏
    ArcGIS Server SOE开发之奇怪异常:
    C# 读取XML注释
    .Net程序员之不学Java做安卓开发:奇怪的Java语法
    .Net程序员之不学Java做安卓开发:Android Studio中的即时调试窗口
    JS去遍历Table的所有单元格中的内容
    判断 checkbox 是否选中以及 设置checkbox选中
  • 原文地址:https://www.cnblogs.com/real-l/p/9353367.html
Copyright © 2020-2023  润新知