以下代码都是本人代码,非队友代码
由于某些不可抗力因素,补题的顺序有点乱
1001:好神仙的辗转相除,听了杜老师的讲解后恍然大悟
稍微推一下式子就发现我们要解下列不等式
其中a,b,c,d固定,要求x最小
我们发现当a/b与c/d之间有整数时,那么显然x取大于a/b小于c/d最小整数,y取1即可
否则我们考虑a/b与c/d的整数部分为t,那么
以上是辗转相除,不难发现该过程必然满足最优性
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int T;
ll p,a,x,y;
void solve(ll a,ll b,ll c,ll d){
// cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
if ((a%b==0?a/b:a/b+1)<=c/d) {
x=(a%b==0?a/b:a/b+1); y=1;
} else {
ll t=c/d;
solve(b,a-b*t,d,c-d*t);
ll p=x;
x=y+x*t; y=p;
}
}
int main(){
scanf("%d",&T);
while (T--){
scanf("%lld%lld",&p,&a);
solve(p,a,p,a-1);
printf("%lld/%lld\n",x*a-p*y,x);
}
}
1002:
%%%神仙队友fyy
我们考虑贪心每次从数组a,b中选出一对xor起来最小的,其正确性显然
先讲讲我的思路:对于两个数组建个trie然后往上合并,后来感觉这种想法怎么样都要2个log就弃疗了
fyy:只要每次找的时候如果都有左右儿子就随便递归一个(不记得他原话怎么讲了)(%%%*2)
然后就被队友带飞了
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int M=30;
int a[N],b[N],c[N],s[M];
int f1[N*M][2],f2[N*M][2],sum1[N*M],sum2[N*M];
int T,n,x,cnt1,cnt2;
void put1(int x){
for (int i=0;i<=29;i++) {
if (x&1) s[i]=1; else s[i]=0;
x>>=1;
}
int now=1; sum1[now]++;
for (int i=29;i>=0;i--)
if (f1[now][s[i]]) now=f1[now][s[i]],sum1[now]++;
else f1[now][s[i]]=++cnt1,now=cnt1,sum1[now]++;
}
void put2(int x){
for (int i=0;i<=29;i++) {
if (x&1) s[i]=1; else s[i]=0;
x>>=1;
}
int now=1; sum2[now]++;
for (int i=29;i>=0;i--)
if (f2[now][s[i]]) now=f2[now][s[i]],sum2[now]++;
else f2[now][s[i]]=++cnt2,now=cnt2,sum2[now]++;
}
int findans(){
int now1=1,now2=1;
int s=0;
for (int i=29;i>=0;i--)
if (sum1[f1[now1][0]]&&sum2[f2[now2][0]]) {
now1=f1[now1][0]; now2=f2[now2][0];
sum1[now1]--; sum2[now2]--;
} else if (sum1[f1[now1][1]]&&sum2[f2[now2][1]]){
now1=f1[now1][1]; now2=f2[now2][1];
sum1[now1]--; sum2[now2]--;
} else if (sum1[f1[now1][0]]&&sum2[f2[now2][1]]) {
now1=f1[now1][0]; now2=f2[now2][1];
sum1[now1]--; sum2[now2]--;
s+=(1<<i);
} else {
now1=f1[now1][1]; now2=f2[now2][0];
sum1[now1]--; sum2[now2]--;
s+=(1<<i);
}
return s;
}
int main(){
scanf("%d",&T);
while (T--){
scanf("%d",&n);
cnt1=cnt2=1;
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++) scanf("%d",&b[i]);
for (int i=1;i<=n;i++) put1(a[i]),put2(b[i]);
for (int i=1;i<=n;i++) c[i]=findans();
sort(c+1,c+n+1);
for (int i=1;i<n;i++) printf("%d ",c[i]);
printf("%d\n",c[n]);
for (int i=1;i<=cnt1;i++) f1[i][0]=f1[i][1]=0,sum1[i]=0;
for (int i=1;i<=cnt2;i++) f2[i][0]=f2[i][1]=0,sum2[i]=0;
}
}
1003:啥是计算几何*1
1004:队友写了说是**题,然后我也不想补了(其实是作者懒)
1005:直接暴力枚举差分数组即可
#include<bits/stdc++.h>
using namespace std;
const int N=50;
int a[N];
bool b[N];
int T,n,k;
void dfs(int now,int t,int t_min,int t_max){
if (now>=n) k--;
else {
for (int i=-n;i<=-1;i++)
if (abs(min(t_min,t+i))+t_max<=n-1&&!b[n+t+i]){
b[n+t+i]=1; a[now]=i; dfs(now+1,t+i,min(t_min,t+i),t_max);
if (!k) return;
a[now]=0; b[n+t+i]=0;
}
for (int i=1;i<=n;i++)
if (max(t_max,t+i)+abs(t_min)<=n-1&&!b[n+t+i]){
b[n+t+i]=1; a[now]=i; dfs(now+1,t+i,t_min,max(t+i,t_max));
if (!k) return;
a[now]=0; b[n+t+i]=0;
}
}
}
int main(){
scanf("%d",&T);
while (T--){
scanf("%d%d",&n,&k);
b[n]=1;
dfs(1,0,0,0);
int s=0,t_min=n*2,t_max=-n*2;
for (int i=1;i<=n-1;i++) {
s+=a[i]; t_min=min(t_min,s); t_max=max(t_max,s);
// cout << s <<endl;
}
int now=0;
if (t_min<0) now=abs(t_min)+1; else now=n-t_max;
printf("%d",now);
for (int i=1;i<=n-1;i++){
now+=a[i]; printf(" %d",now);
}
printf("\n");
for (int i=1;i<=n*2;i++) a[i]=b[i]=0;
}
}
1006:
队友把签到题扔给我然后我差点签到失败了
据说这是扩展kmp板子??然而我用的是kmp.....
他就是要求lcp(1,0)+lcp(2,0)+....lcp(len-1,0)+len-1-那些后缀是前缀的情况
然后反过来考虑对于每个j有多少个i其lcp(i,0)>=j-i+1,然后冷静一下就是nxt数组
然后我忘记初始化了,自己把自己D了一顿
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int T,len;
char s[N];
int sum[N],nxt[N];
void init()
{
nxt[1]=0;
for (int i=2;i<=len;i++)
{
nxt[i]=nxt[i-1];
while (s[nxt[i]+1]!=s[i]&&nxt[i]) nxt[i]=nxt[nxt[i]];
if (s[nxt[i]+1]==s[i]) nxt[i]++,sum[i]=sum[nxt[i]]+1;
}
}
int main(){
scanf("%d",&T);
while (T--){
scanf("%s",s+1);
len=strlen(s+1);
memset(nxt,0,sizeof(nxt));
memset(sum,0,sizeof(sum));
init();
long long ans=0;
for (int i=2;i<=len;i++) ans+=(long long)sum[i];
printf("%lld\n",ans-(long long)sum[len]+(long long)len-1);
}
}
1007:
小于x的数与大于y的数都是固定的,然后转化为从1走到n,每次走一步或者三步
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
const int N=1e5+10;
int f[N];
int T,n,x,y;
void init(){
f[1]=1; f[2]=1;
for (int i=3;i<N;i++)
f[i]=(f[i-1]+f[i-3])%mod;
}
int main(){
scanf("%d",&T);
init();
while (T--){
scanf("%d%d%d",&n,&x,&y);
if (x!=1) x++; if (y!=n) y--;
if (x>y) printf("%d\n",0);
else
printf("%d\n",f[abs(y-x)+1]);
}
}
1008:
队友在考场上写完死活过不去原因竟然是没看答疑:三点共线中的点也要对称!!!
我:啥是计算几何*2
1009:
考场上川爷:这是loj原题
然后我们兴致勃勃的翻到了原题竟然是.....
结果发现loj上的模数是固定的,而且还要预处理模数.....
自闭了.......
赛后据说是Pohlig Hellman算法(听都没听过)
还听说这东西对于CTF就相当于最短路对于ICPC......
自闭了*2.......