HDU

来源:互联网 发布:网络助手怎么用? 编辑:程序博客网 时间:2024/06/06 00:43


hdu 4135
题意:

给一个区间[a,b],从区间[a,b]中找出共有多少个数是与n互质的。

思路:

很水的一个容斥,由于1e9以内的因子很少,所以我们很容易想到预处理n所有的因子,然后求出[1,a-1]和[1,b]中和n不互质的个数,然后求差即可得到和n互质的个数了.

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 1e7+5;ll prime[maxn],cnt;ll a,b,n;int num[maxn];void init(ll x){    cnt = 0;    prime[++cnt] = x;    for(ll i = 2;i * i <= x;++i)    {        if(x % i == 0)        {            prime[++cnt] = i;            if(i != x/i)            {                prime[++cnt] = x/i;            }         }    }    sort(prime+1,prime+cnt+1);    return ;}ll solve(ll x){    if(x == 0) return 0;    ll res = 0;    //cout<<cnt<<endl;    for(int i = 1;i <= cnt;++i)    num[i] = 1;    for(int i = 1;i <= cnt;++i)    {        if(!num[i]) continue;        res = res +  x/prime[i]*num[i];        for(int j = 1 + i;j <= cnt;++j)        {            if(prime[j] % prime[i]) continue;            num[j] -= num[i];        }    }    return res;}int main(){    int _,ca = 1;    cin>>_;    while(_--)    {        ll ans;        scanf("%lld %lld %lld",&a,&b,&n);        if(n == 1)        ans = b-a+1;        else        {            init(n);            ans = solve(b) - solve(a-1);            //printf("%lld %lld\n",solve(a-1),solve(b));            ans = b - a + 1 - ans;              }        printf("Case #%d: %lld\n",ca++,ans);    }    return 0;} /*100 20 21 201 20 201 10 10 */

看网上大牛们还有其他别的写法,1e9以内的素数很少可以二进制枚举组合然后奇+偶-进行容斥.还有用队列和dfs容斥的.

附上dfs容斥代码:

#include<cstdio>#include<cstring>#include<iostream>using namespace std ;const int maxn = 100010 ;typedef __int64 ll ;ll p[maxn] ;int len ;void get_prime(ll n){    len = 0 ;    for(ll i = 2;i*i <= n;i++)    {        if(n%i == 0)p[++len] = i ;        while(n%i == 0)n/=i ;    }    if(n>1)p[++len] = n;}ll dfs(int pos , ll n){    ll ans = 0 ;    for(int i = pos ;i <= len ;i++)        ans += n/p[i] - dfs(i+1 , n/p[i]) ;    return ans ;}int main(){    ll a , b ,n ;    int T ;    int cas =  0 ;    scanf("%d" ,&T) ;    while(T--)    {        scanf("%I64d%I64d%I64d" , &a , &b , &n);        get_prime(n) ;        ll ans = (b - dfs(1 , b)) - (a  - 1 - dfs(1 , a-1)) ;        printf("Case #%d: " ,++cas) ;        printf("%I64d\n" , ans) ;    }    return  0 ;}
原创粉丝点击