CF 818 div2

菜且浮躁。

A 题目的限制 利用唯一分解定理后变为 a b的质因子差只能为2或3且一个。

答案 就为 (n/2+n/3)*2+n 乘2因为a b可以互换。

B 给出来一个关键点 构造出大小为\(n*n\)\(.\)\(X\)正阵 以及一个k 要求任意\(1*k\)或者\(k*1\)的矩阵内有至少一个\(X\)\(X\)的数量最少 且关键点必须为\(X\)

规律题,有点阴间,我是正常想但没想到结论。旁边的同学一眼看到关键点(x,y) (x+y)%k相同的所有点为\(X\)就做完了。

事实上 我在做没关键点版本的 但是也没有一个很好的结论。下面是赛后思考:

容易想到一个无关键点的方阵每次放斜线比较优 但在k的限制下我们有可能只放一个斜线是不合法的 下一个斜线放哪呢

把所有斜线标出来 从上到下歇着标号 距离上一个斜线距离为k即可。

注意这条斜线如果是左上到右下则 (x+y) 在一条斜线上相同 对于右上到左下(x-y) 相同。

至于第一条斜线放的位置可以枚举了。

对于有关键点的可以考虑第一条斜线放关键点那条斜线或者就关键点那放一个剩下采取最小放置X的斜线位置(枚举第一条斜线位置)

事实上 后者没必要可能是其余不优的第一条斜线=最优第一条斜线+1 才导致这种情况发生。(口胡的没验证。

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define a(x) t[x].a
#define sum(x) t[x].sum
#define b(x) t[x].b
#define F first
#define S second
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    return x*f;
}
const int MAXN=1000010;
int T;
int n,x,y,k;

signed main()
{
	freopen("1.in","r",stdin);
	T=read();
	while(T--)
	{
		n=read();k=read();x=read();y=read();
		x=(x+y)%k;
		rep(1,n,i)
		{
			rep(1,n,j)
			if((i+j)%k==x)cout<<'X';
			else cout<<'.';
			cout<<endl;
		}
	}
	return 0;
}

C 给出一个数组a 和 一个数组b 若 \(a_i\leq a_{i+1}\) 就可以让\(a_i+1\) \(a_{n+1}->a_1\)

问最后a数组和b数组能否相同。

如果初始a b相同直接就判断了。如果初始\(a_i>b_i\)也是一样。

接下来考虑不为上述两种情况的情况:一个容易发现的事实若\(b_{i+1}+1<b_i\)\(a_i!=b_i\)同样不合法。

继续思考,如果上述3种情况没有发生是否一定合法呢?我是利用递归法证明的:现在的这个序列选择两个数列的数字开始加直到其中一个数字被加到\(b_i\)

那么根据上述条件3可知旁边的的数字也可以成立 递归来看整个序列可以合法。

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define a(x) t[x].a
#define sum(x) t[x].sum
#define b(x) t[x].b
#define F first
#define S second
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    return x*f;
}
const int MAXN=200010;
int T;
int n;
int a[MAXN],b[MAXN],nex[MAXN];
int main()
{
//	freopen("1.in","r",stdin);
	T=read();
	while(T--)
	{
		n=read();int flag=0;
		rep(1,n,i)a[i]=read(),nex[i]=i+1;
		nex[n]=1;
		rep(1,n,i)b[i]=read();
		rep(1,n,i)
		{
			if(b[i]<a[i])flag=1;
			if(b[i]>=b[nex[i]]+2&&a[i]!=b[i])flag=1;
		}
		if(flag){puts("NO");continue;}
		puts("YES");
	}
	return 0;
}

D 给出一个n 和k 有\(2^n\)个选手比赛 选手比赛顺序任意 但获胜的位置固定 但有k次可能被干扰 问在k次干扰下可以使得得到胜者至少多小、

可以发现我们只需要对胜者x的路径进行更改即可,同时若在一轮中进行两次操作是无效的。

由于获胜路径固定 对于某一种获胜路径来说可以利用一个长度为n的二进制数第i位表示第i轮能否获胜1不能获胜0。一个数字能获胜当且仅当0的数量小于等于k。

为了使结果尽可能小 我们把所有能获胜的用较小的数字去填即可 答案为 \(\sum_{i=0}^{min(n,k)}C(n,i)\)

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define a(x) t[x].a
#define sum(x) t[x].sum
#define b(x) t[x].b
#define F first
#define S second
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    return x*f;
}
const int MAXN=200010;
int T,len,n,k;
inline int ksm(int b,int p)
{
	int cnt=1;
	while(p)
	{
		if(p&1)cnt=((ll)cnt*b)%P;
		p=p>>1;b=(ll)b*b%P;
	}
	return cnt;
}
inline int solve(int dep,int res)
{
	if(!res)return 1;
	return (ksm(2,dep)+solve(dep-1,res-1))%P;
}
int inv[MAXN];
int main()
{
	freopen("1.in","r",stdin);
	n=read();k=read();
	if(k>=n){printf("%d\n",ksm(2,n));return 0;}
	inv[1]=1;
	rep(2,n,i)inv[i]=(ll)inv[P%i]*(P-P/i)%P;
	int C=1,ans=1;
	rep(1,k,i)//C(n,i)=C(n,i-1)/i*(n-i+1)
	{
		C=(ll)C*inv[i]%P*(n-i+1)%P;
		ans=(ans+C)%P;
	}
	printf("%d\n",ans);
	return 0;
}

E 对于任意正整数三元组 \((a,b,c)\) 满足 \(a+b+c = n\)。求 \(\sum{\operatorname{lcm}(c, \gcd(a, b))}\) 的值。答案对 \(10^9+7\) 取模。

枚举c 得到 a+b=n-c; 先不将lcm变形,考虑枚举d=gcd(a,b) 显然 d|n-c

把式子写一下 \(\sum_{c=1}^{n-2}\sum_{d|(n-c)}LCM(d,c)\sum_{a=1}^{n-c}[(a,n-c-a)==d]\)

套路是将后面式子除以d \(\sum_{c=1}^{n-2}\sum_{d|(n-c)}LCM(d,c)\sum_{a=1}^{(n-c)/d}[(a,(n-c)/d-a)==1]\)

后者利用gcd的变形 (a,(n-c)/d-a)=(a,(n-c)/d) 但值得注意的是(n-c)/d-a不应该等于0即(n-c)/d不能等于1

最后 这个式子其实是 \(\sum_{a=1}^{(n-c)/d}[(a,(n-c)/d)==1]=phi[(n-c)/d]\) 注意(n-c)/d是否为1即可。

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007
#define mod 1000000007
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define a(x) t[x].a
#define sum(x) t[x].sum
#define b(x) t[x].b
#define F first
#define S second
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    return x*f;
}
const int MAXN=100010;
int n,ans,top;
int p[MAXN],v[MAXN],phi[MAXN];
inline void init()
{
	phi[1]=0;
	rep(2,n,i)
	{
		if(!v[i])
		{
			p[++top]=i;
			v[i]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=top;++j)
		{
			if(p[j]>v[i]||i>n/p[j])break;
			v[i*p[j]]=p[j];
			if(i%p[j])phi[i*p[j]]=phi[i]*(p[j]-1);
			else phi[i*p[j]]=phi[i]*p[j];
		}
	}
}
inline int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}
inline void js(int c,int d)
{
	ans=(ans+(ll)c*d/gcd(c,d)%mod*phi[(n-c)/d]%mod)%mod;
}
inline void calc(int x)
{
	int ww=n-x;
	for(int w=1;w*w<=ww;++w)
	{
		if(ww%w==0)
		{
			js(x,w);
			if(ww/w!=w)js(x,ww/w);
		}
	}
}
int main()
{
	freopen("1.in","r",stdin);
	n=read();
	init();
	rep(1,n-2,c)calc(c);
	printf("%d\n",ans);
	return 0;
}
posted @ 2022-09-05 15:26  chdy  阅读(26)  评论(0编辑  收藏  举报