[考试反思]0603四校联考第一轮day1:星辰
开学第一场考试是辣鸡$whzzt$出的题。题目毒瘤题解瞎写。
这套题体验又是极差。
虽说前俩题爆零这个事吧。。。
$T1$为了卡常于是改了变量名然后没改全挂了$10pts$问题不大。
$T2$无解判定少写了一条直接把$20pts$也挂没了问题依然不大。
$T3$的$60pts$倒是不低勉强扛住了这场的排名。
然而这次关键是在$T1$。并不是很难,但是根本没有砸时间。
在学校状态比在家是会好一些,貌似。不知道不吃早饭有没有影响。
只剩下$7$场模拟了。。。
T1:解码
大意:给定$n,m,c$。存在奇质数$p,q$使$pq=n,2 \le q-p \le 3 \times 10^5$,有$(c,(p-1)(q-1))=1$。求一个$x$使得$x^c \equiv m (\mod n)$。$10^9 \le p \le 2 \times 10^9,T \le 10^5$
答案肯定有$m^{\frac{1}{c}} (\mod n)$。$c$关于$\varphi(n)$有逆元所以直接搞就可以。
问题在于快速求$phi$也就是快速得到$p,q$。我们有$pq=n$。设$q=p+y$则有$p^2+py=n$。也就有$p=\frac{-y + \sqrt{y^2+4n}}{2}$
为了让它是个整数,所以$y^2+4n$一定要是$4$的倍数且为完全平方数。设$t=\frac{y}{2}$则有$t^2+n=k^2$
我们枚举$k$,下界是$\sqrt{n}$。由于$p \ge 10^9$此后$k$每增加$1$都会使$k^2$增加$O(10^9)$。
根据题意我们有$t \le 1.5 \times 10^5$。所以$t^2$这一项最多也就增长$\frac{(1.5 \times 10^5)^2}{10^9}=15$次左右。所以只需要枚举$k$就行了。
需要快速乘。时间复杂度$O(Tlogn+15T)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 ll n,m,c; 5 ll mul(ll a,ll b,ll m){return ((a*b-(ll)(1.L*a/m*b)*m)%m+m)%m;} 6 ll qp(ll b,ll t,ll m,ll a=1){for(;t;t>>=1,b=mul(b,b,m))if(t&1)a=mul(a,b,m);return a;} 7 void exgcd(ll a,ll b,ll&x,ll&y){ 8 if(!b){x=1;y=0;return;} 9 exgcd(b,a%b,x,y);ll r=x;x=y;y=r-a/b*x; 10 } 11 ll inv(ll a,ll b){ll x,y;exgcd(a,b,x,y);return (x%b+b)%b;} 12 int main(){freopen("rsa.in","r",stdin);freopen("rsa.out","w",stdout);int t;scanf("%d",&t);while(t--){ 13 scanf("%lld%lld%lld",&n,&m,&c); 14 ll k,t,p,q,phi; 15 k=sqrt(n); 16 while(1){ 17 t=sqrt(k*k-n); 18 if(t*t+n==k*k)break;k++; 19 }phi=(k-t-1)*(k+t-1); 20 printf("%lld\n",qp(m,inv(c%phi,phi),n)); 21 }}
T2:排列
大意:给定长为$n$的数列$x$,构造$m$个长为$n$的排列$P_i$并赋权$v_i$使得$0 \le v_i \le 1,\sum v_i =1,\sum P_iv_i=x,m \le n$。$n \le 500,eps=10^{-4}$
首先考虑无解判定。
$\sum\limits_{i=1}^{n} x_i = \frac{n(n+1)}{2}$
$\forall N\le n,\sum\limits_{i=1}^{N} x_i \ge \frac{N(N+1)}{2}$
必要性比较显然。
充分性的话,考虑把$n!$种可能的排列都表示为$n$维向量,那么满足上述条件的点构成的是一个平面凸包($\sum v_i =1$的限制所致)
进而考虑构造方法:每次按照当前的数列$x$的元素大小顺序构造排列$P_i$。也就是最小的位置$a$对应$P_{i,a}=1$这样。
然后可以二分$v_i$的值,存在单调性(如果减的数量不够那就再减一轮)。
由于一个任意$n$维向量均可以由$n$个非线性相关的$n$维向量线性表出,所以一定可以构造出解。
稍微卡精。$O(n^2log\ eps)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ldb long double 4 #define eps 1e-12L 5 #define S 505 6 ldb r[S],a[S],rat=1;int n,x[S],p[S]; 7 bool chk(){ 8 sort(r+1,r+1+n); ldb tot=0; 9 for(int i=1;i<=n;++i){tot+=r[i]-rat*i;if(tot<-eps)return 0;} 10 return fabs(tot)<=eps; 11 } 12 bool cmp(int x,int y){return a[x]<a[y];} 13 int main(){ 14 freopen("permutation.in","r",stdin);freopen("permutation.out","w",stdout); 15 scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%Lf",&a[i]),r[i]=a[i],x[i]=i; 16 if(!chk())return puts("-1"),0; printf("%d\n",n); 17 for(int _=1;_<=n;++_){ 18 sort(x+1,x+1+n,cmp); for(int i=1;i<=n;++i)p[x[i]]=i; 19 ldb L=0,R=rat,m; 20 while(m=(L+R)/2,R-L>1e-14L){ 21 for(int i=1;i<=n;++i)r[i]=a[i]-p[i]*m; 22 rat-=m;if(chk())L=m;else R=m;rat+=m; 23 } 24 for(int i=1;i<=n;++i)a[i]-=p[i]*L;rat-=L; 25 printf("%.9Lf ",L); 26 for(int i=1;i<=n;++i)printf("%d ",p[i]);puts(""); 27 } 28 }
T3:安排
先咕掉,等$WK$讲或者再看看$std$再说。