容斥原理+质因数分解+组合数学


poj 3904---容斥原理

hdu 1695---容斥原理

poj 1091---容斥原理

poj 2773---二分+容斥原理


poj 3904---容斥原理

http://blog.csdn.net/duanxian0621/article/details/7313707

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define N 10010

int p[N],g[N];
int t[20];
ll h[N];
void solve(int x)
{
	int i,j,k,cnt=0;
	for(i=2;i*i<=x;i++)
	{
		if(x%i==0)
		{
			t[cnt++]=i;
			while(x%i==0)
				x/=i;
		}
	}
	if(x!=1)
		t[cnt++]=x;
	int tt=(1<<cnt);
	for(i=1;i<tt;i++)
	{
		int tsum=1,tflag=0;
		for(j=0;j<cnt;j++)
		{
			if((i>>j)&1)
			{
				tsum*=t[j];
				tflag++;
			}
		}
		p[tsum]++;
		g[tsum]=tflag;
	}
}
int main()
{
	int n;
	ll i,j,k;
	h[0]=h[1]=h[2]=h[3]=0;
	for(i=4;i<=10000;i++)
	{
		h[i]=i*(i-1)*(i-2)*(i-3)/24;
	}
	while(scanf("%d",&n)!=EOF)
	{
		memset(p,0,sizeof(p));
		memset(g,0,sizeof(g));
		for(i=0;i<n;i++)
		{
			scanf("%d",&k);
			solve(k);
		}
		ll res=h[n];
		for(i=1;i<=10000;i++)
		{
			if(p[i]!=0)
			{
				if(g[i]&1)
					res-=h[p[i]];
				else
					res+=h[p[i]];
			}
		}
		cout<<res<<endl;
	}
}

hdu 1695---容斥原理

http://www.cnblogs.com/jiaohuang/archive/2011/01/15/1936509.html

#include<cstdio>  
#include<cstring>  
#include<string.h>
#include<stdio.h>
#include<algorithm>  
#include<iostream>  
#include<cstdlib>  
#include<vector>  
#include<set>
#include<cmath>  
#include<math.h>
using namespace std;  
#define inf 0x3f3f3f3f  
#define ll __int64
#define N 100010

int prime[N+10];  
ll phi[N+10];  
ll sum[N+10]; 
void dabiao()  
{  
    int i,j,k;  
    memset(prime,0,sizeof(prime));  
    for(i=2;i*i<N;i++)  
        if(!prime[i])  
            for(j=i*i;j<N;j+=i)  
                prime[j]=1;  
    for(i=1;i<N;i++)  
        phi[i]=i;  
    for(i=2;i<N;i++)  
        if(!prime[i])  
            for(j=i;j<N;j+=i)  
                phi[j]=phi[j]/i*(i-1);  
    sum[1]=1;  
    //sum[2]=phi[2];  
    for(i=2;i<N;i++)  
        sum[i]=sum[i-1]+phi[i];  
}  

int h[30];
int main()
{
	int i,j,k,t;
	scanf("%d",&t);
	int he=0;
	dabiao();
	while(t--)
	{
		he++;
		int a,c,b,d;
		scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
		if(k==0)
		{
			printf("Case %d: 0\n",he);
			continue;
		}
		if(b>d) swap(b,d);
		b/=k,d/=k;
		ll res=sum[b];
		for(i=b+1;i<=d;i++)
		{
			res+=b;
			int cnt=0;
			int te=i;
			for(j=2;j*j<=te;j++)
			{
				if(te%j==0)
				{
					h[cnt++]=j;
					while(te%j==0)
						te/=j;
				}
			}
			if(te!=1)
				h[cnt++]=te;
			int tt=(1<<cnt);
			for(j=1;j<tt;j++)
			{
				int tsum=1,tflag=0;
				for(k=0;k<cnt;k++)
				{
					if((j>>k)&1)
					{
						tsum*=h[k];
						tflag++;
					}
				}
				if(tflag&1)
					res-=b/tsum;
				else
					res+=b/tsum;
			}
		}
		printf("Case %d: %I64d\n",he,res);
	}
}

poj 1091---容斥原理

http://blog.csdn.net/bobten2008/article/details/4473864

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define N 10010

int t[20];
int n;
ll m;
ll qpow(ll x)
{
	ll sum=1;
	for(int i=0;i<n;i++)
		sum*=x;
	return sum;
}
void solve(ll x)
{
	int i,j,k,cnt=0;
	for(i=2;i*i<=x;i++)
	{
		if(x%i==0)
		{
			t[cnt++]=i;
			while(x%i==0)
				x/=i;
		}
	}
	if(x!=1)
		t[cnt++]=x;
	int tt=(1<<cnt);
	ll res=qpow(m);
	for(i=1;i<tt;i++)
	{
		int tsum=1,tflag=0;
		for(j=0;j<cnt;j++)
		{
			if((i>>j)&1)
			{
				tsum*=t[j];
				tflag++;
			}
		}
		if(tflag&1)
			res-=qpow(m/tsum);
		else
			res+=qpow(m/tsum);
	}
	cout<<res<<endl;
}

int main()
{
	int i,j,k;
	scanf("%d%lld",&n,&m);
	solve(m);
	//system("pause");
}


poj 2773---二分+容斥原理

<pre name="code" class="cpp">#include<iostream>  
#include<stdio.h>  
#include<string.h>  
#include<algorithm>  
using namespace std;  
#define ll long long  
#define inf 0x3f3f3f3f  
#define N 10010  
  
ll gcd(ll a,ll b)  
{  
    return b?gcd(b,a%b):a;  
}  
ll h[20];  
ll p[20000];  
ll f[20000];  
ll tcnt;  
  
ll solve(ll x)  
{  
    ll res=x;  
    for(ll i=0;i<tcnt;i++)  
    {  
        if(f[i]&1)  
            res-=x/p[i];  
        else  
            res+=x/p[i];  
    }  
    return res;  
}  
int main()  
{  
    ll i,j,k,m;  
    while(scanf("%lld%lld",&m,&k)!=EOF)  
    {  
        ll l=0,r=1000000000000,mid,ans,flag;  
        ll cnt=0,t=m;  
        for(i=2;i*i<=t;i++)  
        {  
            if(t%i==0)  
            {  
                h[cnt++]=i;  
                while(t%i==0)  
                    t/=i;  
            }  
        }  
        if(t!=1)  
            h[cnt++]=t;  
        ll tt=(1<<cnt);  
        tcnt=0;  
        for(i=1;i<tt;i++)  
        {  
            ll tsum=1,tflag=0;  
            for(j=0;j<cnt;j++)  
            {  
                if((i>>j)&1)  
                {  
                    tsum*=h[j];  
                    tflag++;  
                }  
            }  
            p[tcnt]=tsum;  
            f[tcnt++]=tflag;  
        }  
        while(l<r)  
        {  
            mid=(l+r)/2;  
            ans=solve(mid);  
            if(ans>=k)
				r=mid;
			else
				l=mid+1;
        }  
        printf("%lld\n",r);  
    }  
}  



                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值