[FR#12]被虐賽

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);
}



發佈了48 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章