[FR#12]被虐赛

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yfzcsc/article/details/55684233

A题题意:有一个序列a1...an,您需要回答m个询问,每个询问给一个b,使删除尽量少的数使得任意时刻前缀和都>=b(m<=10^4,n<=10^3)

由于FLOJ跑的太快了,导致没有数据可以卡掉O(mnlogn)

我倒是写了一个整体二分求ans[i]表示需要删i个数时的最小b,O(nlogn*30+mlogn)?

正解:dp[i][j]表示a1..ai中删j个数时的最小前缀和,询问时二分,O(mlogn+n^2)


B题题意:给定n,m,p(n,m,p<=1e7)求然后求

两道题组合即视感。。。
对于Part I:求一个f(i),它其实就是一个假phi,只是在设初值时f[p]=(n%p==0?p:p-1)(p为质数)再O(m)求和
对于Part II:搞一个f(k,p)为答案,则 它一定会在O(log n)的时间中得到p<=1。。。没了


C题题意:求 其中f(0)=0,f(1)=1,f(n)=f(n-1)+f(n-2)(n>=2),(an<=1000000,n<=50000)

首先您需要知道一个定理:f(gcd(x,y))=gcd(f(x),f(y))(证明略。。。)
这样,我们就可以直接考虑下标间的关系了

然后有这样一个容斥式子:于是我们就可以考虑求每个i的贡献

于是:设F(i)为i|gcd的a的贡献,则F(i)=C(1,F(i))-C(2,F(i))+C(3,F(i))...=[F(i)!=0]

           设G(i)为i=gcd的a的贡献,G(i)=F(i)-G(2i)-G(3i)-...

然后用快速幂累乘即可,O(ClogC)(C<=1e6)

AC Code:

B题:

#include<bits/stdc++.h>
#define maxn 10001000
using namespace std;
typedef long long ll;
int phi[maxn],m,n,p,phi2[maxn],pri[maxn],psz,vis[maxn];
int qpow(int a,int b,int p){
	int ans=1,tmp=a;
	for(;b;b>>=1,tmp=1ll*tmp*tmp%p)
		if(b&1)ans=1ll*ans*tmp%p;
	return ans;
}
int find(int k,int p){
//	printf("[%d,%d]\n",k,p);
	if(k==0)return 1;
	if(p==1)return 0;
	return qpow(k,find(k,phi[p])+phi[p],p);
}
int main(){
	scanf("%d%d%d",&m,&n,&p);
	phi[1]=phi2[1]=1;
	int lim=max(max(m,n),p);
	for(int i=2;i<=lim;i++){
		if(!vis[i]){pri[psz++]=i;phi[i]=i-1;phi2[i]=(m%i==0?i:i-1);}
		for(int j=0;j<psz&&i*pri[j]<=lim;++j){
			vis[i*pri[j]]=true;
			if(i%pri[j]){
				phi[i*pri[j]]=phi[i]*phi[pri[j]];
				phi2[i*pri[j]]=phi2[i]*phi2[pri[j]];
			} else {
				phi[i*pri[j]]=phi[i]*pri[j];
				phi2[i*pri[j]]=phi2[i]*pri[j];
			}
		}
	}
	ll k=0;
	for(int i=1;i<=n;++i)k=(k+1ll*phi2[i]*phi[m])%1000000007;
//	printf("[%d]",k);
	printf("%d",find(k,p));
}

C题:

#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
int f[1000100],F[1000100],G[1000100],a[50100],n,ans=1;
int qpow(int a,int b,int p){
	int tmp=a,ans=1;
	for(;b;b>>=1,tmp=1ll*tmp*tmp%p)
		if(b&1)ans=1ll*ans*tmp%p;
	return ans;
}
int main(){
	f[0]=0,f[1]=1;
	for(int i=2;i<=1000000;++i)f[i]=(f[i-1]+f[i-2])%mod;
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	for(int i=1;i<=n;++i)
		for(int j=1;j*j<=a[i];++j)if(a[i]%j==0){
			F[j]++;if(j*j!=a[i])F[a[i]/j]++;
		}
//	for(int i=1;i<=n;++i)ans=1ll*ans*f[a[i]]%mod;
//	printf("[%d]",ans);
	for(int i=1000000;i>=1;--i){
		G[i]=(F[i]!=0);
		for(int j=2*i;j<=1000000;j+=i)
			G[i]-=G[j];
//		if(G[i])printf("[%d:%d]",f[i],G[i]);
		if(G[i]<0)ans=1ll*ans*qpow(f[i],mod-1+G[i],mod)%mod;
		else if(G[i])ans=1ll*ans*qpow(f[i],G[i],mod)%mod;
	}
	printf("%d",ans);
}



阅读更多
换一批

没有更多推荐了,返回首页