• POj-1091 跳蚤


    原题链接:http://poj.org/problem?id=1091

    题目大意:给你两个数n和m;总共有m^n张卡片,每张卡片上有n+1个数字,然后根据卡片上的数字可以向左跳也可以向右跳,每个数字跳的次数任意,直到跳达刚开始左边一个单位的地方

    解题思路:把卡片上的数字用x1,x2,x3…xn,m表示,跳的次数可以用a1,a2,a3…an+1表示,于是可以得到:

    a1x1+a2x2+…+anxn+an+1m=1;

    这个式子是不是很像扩展欧几里得里的ax+by=gcd(a,b)=1;所以我们就可以想到只要保证gcd(a1,a2,a3…an+1)==1,就说明该卡片可以完成任务。而这样正着求比较难求(反正我不会),我们可以求出不满足的即gcd(a1,a2,a3…an+1)!= 1,即不互质,因为每张卡片都有m,那只要有一个数和m不互质就可以了,可以用到唯一分解定理来分解m,然后反着用容斥定理,奇减偶加;即可求出答案。

    Code:

    #include<iostream>
    #include<cmath>
    #include<vector>
    
    using namespace std;
    typedef long long ll;
    vector<int>ve;
    
    void getprime(int m){//得到m的质因子 
    	ve.clear();
    	for(int i=2;i*i<=m;i++){
    		if(m%i==0){
    			ve.push_back(i);
    		}
    		while(m%i==0){
    			m/=i;
    		}
    	}
    	if(m>1) ve.push_back(m);
    }
    ll ksm(ll m,ll n){//快速幂模板 
    	ll res=1;
    	while(n){
    		if(n&1) res=res*m;
    		n>>=1;
    		m=m*m;
    	}
    	return res;
    }
    
    int main(){
    	int n,m;
    	cin>>n>>m;
    	getprime(m);
    	ll ans=ksm(m,n);//卡片总数 
    //	cout<<ve.size()<<endl;
    	for(int i=1;i<(1<<ve.size());i++){//(1<<ve.size()) 表示2^ve.size()次方 
    		ll cnt=0,sum=1;
    		for(int j=0;j<ve.size();j++){
    			if(1&(i>>j)){
    				cnt++;
    				sum*=ve[j];
    			}
    		}
    		if(cnt&1) ans-=pow(m/sum,n);//奇减偶加 
    		else ans+=pow(m/sum,n);
    	}
    	cout<<ans<<endl;
    	
    	return 0;
    }
    
    七月在野,八月在宇,九月在户,十月蟋蟀入我床下
  • 相关阅读:
    Missing Number
    python乱码,讲得比较好,
    公司搬家,拿了个费机器,没root密码,又忘了怎么搞了,
    mylyn
    eclipse shortcut binding
    jdk8 eclipse luna market crashed
    openjdk
    download plugin update site for offline installation
    armstrong's programming erlang 2nd
    sdf SimpleDateFormat 不是线程安全的,
  • 原文地址:https://www.cnblogs.com/voids5/p/12695020.html
Copyright © 2020-2023  润新知