暑假集训日记——8.1(牛客+codeforce)

容斥原理的应用
正难则反,合取式 的情况不好求,就转化为求解 总数-容斥
小y的质数
题解:容斥原理
在这里插入图片描述

#include<bits/stdc++.h>
#define mp make_pair
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;


const int N=1e7+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=1e9+7;
ll prime[N];
ll cnt;

void gets(ll x)
{
    ll s=sqrt(x);

    for(int i=2;i<=s;i++)
    {
        if(x%i==0)
            prime[cnt++]=i;
        while(x%i==0)
            x=x/i;
    }
    if(x!=1)
        prime[cnt++]=x;
}

ll IEP(ll x)
{
    if(x<0) return 0;
    ll sum=0;
    for(int i=1;i<(1<<cnt);i++)///容斥原理
    {
        ll f=-1,ans=1;
        for(int j=0;j<cnt;j++)///枚举每种质因数的组合
        {
            if(i&(1<<j))
            {
                ans=ans*prime[j];
                f=f*(-1);
            }
        }
        sum=sum+(x/ans)*f;///(x/ans)表示:1-x中有ans因数的个数
    }
    return x-sum;
}

int main()
{
    ll k,r,l,i;
	cin>>l>>r>>k;
	k=k*2;
	r=r-k;
	if((l+k)>r){
		printf("0\n");
		return 0;
	}
	gets(k);
	cout<<IEP(r)-IEP(l-1)<<endl;
}

Tachibana Kanade Loves School
题解:由于数据范围很小直接暴力就可以了,但是我想优化到O(n)的复杂度,然后…就出问题了(卡在水题上…
一开始用 a[i]+b[i]来映射b[i] 来进行比较
虽然a[i] 不同,但a[i]+b[i]可能会有重复然后覆盖掉之前的值!!
所以改一下用a[i] 映射b[i]

#include<bits/stdc++.h>
#define mp make_pair
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;


const int N=1e7+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=1e9+7;
int a[N],b[N];
map<int,int>s;


int main()
{
    int k,r,l,i;
	cin>>k;
	for(int i=1;i<=k;i++)
    {
        cin>>a[i]>>b[i];
        //s[a[i]+b[i]]==-b[i] 重复覆盖
        s[a[i]]=b[i];
    }
    for(int i=1;i<=k;i++)
    {
        if(s[a[i]+b[i]]==-b[i])
        {
            cout<<"YE5"<<endl;
            return 0;
        }
    }
    cout<<"N0"<<endl;
}

Tachibana Kanade Loves Probability
题解:模拟题:模拟除法的过程求小数点后的数
除法:10进制下,正常的计算小数点之后的数,就是先乘10,然后除以被除数,然后取余后的数再进行下一步计算。

#include<bits/stdc++.h>
#define mp make_pair
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;


const int N=1e7+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=1e9+7;
int a[N],b[N];
int s[N];

inline ll qpow(ll a,ll b,ll p){
    ll res = 1;
    for(;b;b>>=1,a=a*a%p)
        if(b&1) res = res * a % p;
    return res;
}

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        ll a,b,k1,k2;
        cin>>a>>b>>k1>>k2;
        ll ans=((a % b)*qpow(10, k1 - 1, b))%b;
        for(ll i=k1;i<=k2;i++,ans=ans%b) {//模拟除法
            ans*=10;
            cout<<ans/b;
        }
        cout<<endl;
    }
    return 0;
}

Tachibana Kanade Loves Review
题解:构造最小生成树
这个简
…这题居然是一道图论,amazing

#include<bits/stdc++.h>
#define mp make_pair
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;


const int N=1e7+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=1e9+7;
int n, g, k, t, m;

inline char nc()
{
    static char buf[10000000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 10000000, stdin), p1 == p2) ? EOF : *p1++;
}

inline int read()
{
    int res = 0;
    char ch;
    do ch = nc(); while (ch < 48 || ch > 57);
    do res = res * 10 + ch - 48, ch = nc(); while (ch >= 48 && ch <= 57);
    return res;
}

struct edge
{
    int x,y;
    int w;
}e[N];

int fa[N];
int rankS[N];
int sum;

int cmp(edge a,edge b)//排序函数
{
    if(a.w!=b.w)
        return a.w<b.w;
    else
        return a.x<b.x;
}
void make_set(int x)//初始化节点
{
  fa[x]=x;
  rankS[x]=0;
}
 int findS(int x)//查找父节点
 {
     return fa[x]==x?x:fa[x]=findS(fa[x]);
 }


 void union_set(int x,int y,int w)//合并节点
 {
     if(rankS[x]>rankS[y])
     {
         fa[y]=x;
     }
     else  if(rankS[x]<rankS[y])
     {
         fa[x]=y;
     }
     else
     {
      rankS[x]++;
      fa[y]=x;
     }
     sum+=w;//总权值加上w
 }


int main(){
    n = read() + 1, g = read(), k = read(), t = read();
    ///n 为构造的初始点
    int w;
    int cnt=-1;
    for (int i=1;i<n;++i)
    {
        w=read();
        e[++cnt].x=i;e[cnt].y=n;e[cnt].w=w;
        make_set(i);
        make_set(n);
    }
    for (int i=1;i<=k;++i)
    {
        w=read();
        e[++cnt].x=w;e[cnt].y=n;e[cnt].w=0;
        make_set(w);
        make_set(n);
    }
    for (int i=1;i<=g;++i)
    {
        int u = read(), v = read();w = read();
        e[++cnt].x=u;e[cnt].y=v;e[cnt].w=w;
        make_set(u);
        make_set(v);
    }
    sort(e,e+cnt+1,cmp);
    sum=0;
    int x,y;
    for(int  i=0;i<=cnt;i++)
    {
        x=findS(e[i].x);
        y=findS(e[i].y);
        w=e[i].w;
        if(x!=y)
        {
            union_set(x,y,w);
        }
        if (sum>t) break;///优化一下
    }
    puts(sum <= t ? "Yes" : "No");
}

Tachibana Kanade Loves Game
题解:容斥原理

#include<bits/stdc++.h>
#define mp make_pair
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;


const int N=1e7+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=1e9+7;
ll n, g, k, t, m,q,cnt;
vector<int> prime = {2, 3, 5, 7, 11, 13, 17, 19};

ll IEP(ll x)
{
    if(x<0) return 0;
    ll sum=0;
    for(int i=1;i<(1<<cnt);i++)///容斥原理
    {
        ll f=-1,ans=1;
        for(int j=0;j<cnt;j++)///枚举每种质因数的组合
        {
            if(i&(1<<j))
            {
                ans=ans*prime[j];
                f=f*(-1);
            }
        }
        sum=sum+(x/ans)*f;///(x/ans)表示:1-x中有ans因数的个数
    }
    return x-sum;
}

int main(){
    cin>>t;
    while(t--)
    {
        cin>>k>>q>>n>>m;
        cnt = upper_bound(prime.begin(),prime.end(), m)-prime.begin();
        if(k==0)
        {
            cout<<"QAQ"<<endl;
            continue;
        }
        if(m!=1)
        {
            ll ans=IEP(n);
            if(ans+min(k-1,n-ans)>=q)
                cout<<"Yes"<<endl;
            else
                cout<<"QAQ"<<endl;
        }
        else
        {
            if(n>=q)
                cout<<"Yes"<<endl;
            else
                cout<<"QAQ"<<endl;
        }

    }
}

121045 / 妈妈的考试
题解:(数论)这可太秀了…
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值