本文主要是介绍poj 1091 跳蚤(不定方程+容斥),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 8731 | Accepted: 2605 |
Description
比如当N=2,M=18时,持有卡片(10, 15, 18)的跳蚤,就可以完成任务:他可以先向左跳10个单位长度,然后再连向左跳3次,每次15个单位长度,最后再向右连跳3次,每次18个单位长度。而持有卡片(12, 15, 18)的跳蚤,则怎么也不可能跳到距他左边一个单位长度的地方。
当确定N和M后,显然一共有M^N张不同的卡片。现在的问题是,在这所有的卡片中,有多少张可以完成任务。
Input
Output
Sample Input
2 4
Sample Output
12
Hint
(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)
(a1,a2,a3,……,an,M)=1 排除公因子非1的情况 总共的情况数是M^n
a1-an都是小于等于M
初始化出M范围内所有的素因子 枚举所有范围内的素因子
例如 有素因子2 所以M内有M/2个数有2这个素因子 有素因子3 所以M内有M/3个数有3这个素因子
所以重复计算了6这个因子 多算了M/6个数 诸如此类。。。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 10010
#define MAXM 100010
#define INF 99999999
#define ll long long
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)using namespace std;ll Read()
{char ch;ll a = 0;while((ch = getchar()) == ' ' | ch == '\n');a += ch - '0';while((ch = getchar()) != ' ' && ch != '\n'){a *= 10;a += ch - '0';}return a;
}void Prll(ll a) //输出外挂
{if(a>9)Prll(a/10);putchar(a%10+'0');
}
ll p[200],tot;
ll ans,tmp;
ll a[200],m,n;
void divide(ll x)
{tot=0;for(ll i=2;i*i<=x;i++){if(x%i==0){tot++;p[tot]=i;while(x%i==0)x/=i;}}if(x!=1){tot++;p[tot]=x;}
}
ll mult(ll a,ll b)
{ll x=1;while(b){x*=a;b--;}return x;
}void dfs(ll x,ll cnt,ll c)//共有c个公共因子
{if(cnt==c){ll num=m;for(ll i=1;i<=c;i++)num/=a[i];tmp+=mult(num,n);return;}for(ll i=x+1;i<=tot;i++){a[cnt+1]=p[i];dfs(i,cnt+1,c);}
}int main()
{//fread;while(scanf("%lld%lld",&n,&m)!=EOF){ans=tot=0;divide(m);for(ll i=1;i<=tot;i++){tmp=0;dfs(0,0,i);if(i&1)ans+=tmp;else ans-=tmp;}ans=mult(m,n)-ans;printf("%lld\n",ans);}return 0;
}
这篇关于poj 1091 跳蚤(不定方程+容斥)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!