容斥原理的应用
正难则反,合取式 的情况不好求,就转化为求解 总数-容斥
小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 / 妈妈的考试
题解:(数论)这可太秀了…