Codeforces Round #741 div.2 A-F题解

视频讲解:BV1iL4y1Y7WU

A. The Miracle and the Sleeper

题目大意

给定两个正整数 l , r   ( 1 ≤ l ≤ r ≤ 1 0 9 ) l,r~(1 \leq l \leq r \leq 10^9) l,r (1lr109) ,求满足 r ≥ a ≥ b ≥ l r \ge a \ge b \ge l rabl 的最大的 $a \mod{b} $ 。

题解

l l l 足够小,那么 a a a 应该取 r r r b b b 应该取 ⌊ r + 1 2 ⌋ \lfloor \frac{r+1}{2} \rfloor 2r+1 ,答案为 ⌊ r − 1 2 ⌋ \lfloor \frac{r-1}{2} \rfloor 2r1
l l l 较大,那么 a = r , b = l a=r,b=l a=r,b=l ,答案为 r m o d    l r\mod{l} rmodl
分界点为 ⌊ r + 1 2 ⌋ \lfloor \frac{r+1}{2} \rfloor 2r+1

参考代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int T,l,r;
	cin>>T;
	while(T--)
	{
		cin>>l>>r;
		if(l<=(r+1)/2)
			cout<<(r-1)/2<<endl;
		else
			cout<<r-l<<endl;
	}
}

B. Scenes From a Memory

题目大意

给定一个十进制下不包含 0 0 0 的整数 n ( 1 ≤ n < 1 0 50 ) n(1 \le n < 10^{50}) n(1n<1050) ,删除最多的数字,使其变为非素数。

给定数据保证有解,若有多组解则输出任意一种即可。

题解

若包含 1 , 4 , 6 , 8 , 9 1,4,6,8,9 1,4,6,8,9 之一,则直接输出一位数即可。
若包含 2 , 5 2,5 2,5 之一且不为首位,则直接输出首位与 2 2 2 5 5 5 即可。
若包含两个 3 , 7 3,7 3,7 ,则直接输出 33 33 33 77 77 77 即可。
剩余只有 37 , 73 , 237 , 273 , 537 , 573 37,73,237,273,537,573 37,73,237,273,537,573 这几种情况。由于保证必定有解,因此不存在 37 , 73 37,73 37,73 这两种无解情况。对于剩余四种情况,显然 27 27 27 57 57 57 合法。

因此,答案必定为二位数,可以通过上述方式分类讨论,也可以直接枚举得到。

参考代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int T,sum[15],pos[15],i,j,k,flag;
	char s[55];
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&k);
		scanf("%s",&s);
		memset(sum,0,sizeof(sum));
		for(i=0;i<k;i++)
		{
			sum[s[i]-'0']++;
			pos[s[i]-'0']=i;
		}
		if(sum[1])
			printf("1\n1\n");
		else if(sum[4])
			printf("1\n4\n");
		else if(sum[6])
			printf("1\n6\n");
		else if(sum[8])
			printf("1\n8\n");
		else if(sum[9])
			printf("1\n9\n");
		else if(sum[2]&&pos[2]!=0)
			printf("2\n%c2\n",s[0]);
		else if(sum[5]&&pos[5]!=0)
			printf("2\n%c5\n",s[0]);
		else if(sum[3]>1)
			printf("2\n33\n");
		else if(sum[7]>1)
			printf("2\n77\n");
		else
		{
			flag=1;
			for(i=0;i<k&&flag;i++)
			{
				for(j=i+1;j<k;j++)
				{
					if((s[i]-'0'+s[j]-'0')%3==0)
					{
						printf("2\n%c%c\n",s[i],s[j]);
						flag=0;
						break;
					}
				}
			}
		}
	}
}

C. Rings

题目大意

有一个长度为 n   ( 2 ≤ n ≤ 2 ⋅ 1 0 4 ) n~(2 \leq n \leq 2\cdot 10^4) n (2n2104) 仅由01构成的字符串 s s s

定义函数 f f f 表示将字符串视为二进制数后再转为十进制数的结果,例如 f ( 001010 ) = 10 f(001010)=10 f(001010)=10

你需要找到满足以下条件的两对整数 ( l 1 , r 1 ) , ( l 2 , r 2 ) (l_1,r_1),(l_2,r_2) (l1,r1),(l2,r2)

  • 1 ≤ l 1 ≤ n , 1 ≤ r 1 ≤ n , r 1 − l 1 + 1 ≥ ⌊ n 2 ⌋ 1 \leq l_1 \leq n,1 \leq r_1 \leq n,r_1-l_1+1\geq \lfloor \frac{n}{2} \rfloor 1l1n,1r1n,r1l1+12n
  • 1 ≤ l 2 ≤ n , 1 ≤ r 2 ≤ n , r 2 − l 2 + 1 ≥ ⌊ n 2 ⌋ 1 \leq l_2 \leq n,1 \leq r_2 \leq n,r_2-l_2+1\geq \lfloor \frac{n}{2} \rfloor 1l2n,1r2n,r2l2+12n
  • 存在非负整数 k k k ,满足 f ( s [ l 1 : r 1 ] ) = f ( s [ l 2 : r 2 ] ) ⋅ k f(s[l_1:r_1])=f(s[l_2:r_2])\cdot k f(s[l1:r1])=f(s[l2:r2])k

题解

由于是二进制下截取子串,因此考虑 k = 2 k=2 k=2 的情况。
∃ i ∈ [ ⌊ n 2 ⌋ + 1 , n ] , s [ i ] = 0 \exist i\in[\lfloor \frac{n}{2} \rfloor+1,n],s[i]=0 i[2n+1,n],s[i]=0 则存在合法情况 ( l 1 , r 1 ) = ( 1 , i ) , ( l 2 , r 2 ) = ( 1 , i − 1 ) , k = 2 (l_1,r_1)=(1,i),(l_2,r_2)=(1,i-1),k=2 (l1,r1)=(1,i),(l2,r2)=(1,i1),k=2

当不存在上述 i i i 时,则表示 s s s 后半段全为 1 1 1
s [ ⌊ n 2 ⌋ ] = 0 s[\lfloor \frac{n}{2} \rfloor]=0 s[2n]=0 ,则存在合法情况 ( l 1 , r 1 ) = ( ⌊ n 2 ⌋ , n ) , ( l 2 , r 2 ) = ( ⌊ n 2 ⌋ + 1 , n ) , k = 1 (l_1,r_1)=(\lfloor \frac{n}{2} \rfloor,n),(l_2,r_2)=(\lfloor \frac{n}{2} \rfloor+1,n),k=1 (l1,r1)=(2n,n),(l2,r2)=(2n+1,n),k=1
s [ ⌊ n 2 ⌋ ] = 1 s[\lfloor \frac{n}{2} \rfloor]=1 s[2n]=1 ,则存在合法情况 ( l 1 , r 1 ) = ( ⌊ n 2 ⌋ , n − 1 ) , ( l 2 , r 2 ) = ( ⌊ n 2 ⌋ + 1 , n ) , k = 1 (l_1,r_1)=(\lfloor \frac{n}{2} \rfloor,n-1),(l_2,r_2)=(\lfloor \frac{n}{2} \rfloor+1,n),k=1 (l1,r1)=(2n,n1),(l2,r2)=(2n+1,n),k=1

参考代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN=20020;
char s[MAXN];

int main()
{
	int T,n,flag,i;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		scanf("%s",s+1);
		flag=0;
		for(i=n/2+1;i<=n;i++)
		{
			if(s[i]=='0')
			{
				printf("%d %d %d %d\n",1,i,1,i-1);
				flag=1;
				break;
			}
		}
		if(!flag)
		{
			if(s[n/2]=='0')
				printf("%d %d %d %d\n",n/2,n,n/2+1,n);
			else
				printf("%d %d %d %d\n",n/2,n-1,n/2+1,n);
		}
	}
}

D1+D2. Two Hundred Twenty One

题目大意

有一个长度为 n   ( 1 ≤ n ≤ 3 ⋅ 1 0 5 ) n~(1 \leq n \leq 3 \cdot 10^5) n (1n3105) 的仅由±组成的字符串 s s s ,其中+可以视为 1 1 1 ,-可以视为 − 1 -1 1 。字符串合法的条件是奇数位之和等于偶数位之和,即 ∑ i = 1 n ( − 1 ) i − 1 s i = 0 \sum_{i=1}^n(-1)^{i-1}s_i=0 i=1n(1)i1si=0

q ( 1 ≤ q ≤ 3 ⋅ 1 0 5 ) q(1 \leq q \leq 3 \cdot 10^5) q(1q3105) 次询问,每次给定区间 [ l , r ]   ( 1 ≤ l ≤ r ≤ n ) [l,r]~(1 \leq l \leq r \leq n) [l,r] (1lrn) ,求最少需要删除多少字符,才能使得子串 s [ l , r ] s[l,r] s[l,r] 合法。

对于Easy Version,只需输出删除数量。
对于Hard Version,还需输出删除方案。

题解

定义字符串 s s s 的权值为 ∑ i = 1 ∣ s ∣ ( − 1 ) i − 1 s i \sum_{i=1}^{|s|}(-1)^{i-1}s_i i=1s(1)i1si
s u m i sum_i sumi 表示子串 s [ 1 , i ] s[1,i] s[1,i] 的权值。
在子串 s [ l , r ] s[l,r] s[l,r] 中删除字符 s i s_i si ,则表示对 s [ i + 1 , r ] s[i+1,r] s[i+1,r] 部分的子串权值取相反数。
由于 s u m i sum_i sumi 在整数上连续,因此不妨设 f ( i ) f(i) f(i) 表示 s [ l , r ] s[l,r] s[l,r] 删除 s i s_i si 后的权值:
f ( i ) = s u m i − 1 − s u m l − 1 − ( s u m r − s u m i ) f(i)=sum_{i-1}-sum_{l-1}-(sum_r-sum_i) f(i)=sumi1suml1(sumrsumi)
易得
f ( i + 1 ) − f ( i ) = s u m i + 1 − s u m i − 1 f(i+1)-f(i)=sum_{i+1}-sum_{i-1} f(i+1)f(i)=sumi+1sumi1

因此 f ( i + 1 ) − f ( i ) f(i+1)-f(i) f(i+1)f(i) 的值必定为 0 0 0 ± 2 \pm 2 ±2

f ( l ) = − s u m r + s u m l f(l)=-sum_r+sum_l f(l)=sumr+suml

f ( r ) = s u m r − 1 − s u m l − 1 = − f ( l ) − s r + s l f(r)=sum_{r-1}-sum_{l-1}=-f(l)-s_r+s_l f(r)=sumr1suml1=f(l)sr+sl

易得 f ( r ) + s r f(r)+s_r f(r)+sr f ( l ) − s l f(l)-s_l f(l)sl 互为相反数。
f ( r ) ≥ 2 f(r)\geq 2 f(r)2 f ( l ) ≤ 0 f(l)\leq 0 f(l)0
f ( r ) ≤ − 2 f(r)\leq -2 f(r)2 f ( l ) ≥ 0 f(l)\geq 0 f(l)0
f ( r ) = 0 f(r)=0 f(r)=0 则直接找到解。
f ( r ) = ± 1 f(r)=\pm 1 f(r)=±1 则无解。
因此

  • f ( r ) f(r) f(r) 为偶数时,由于连续函数性质,必定存在 f ( i ) = 0 f(i)=0 f(i)=0
  • f ( r ) f(r) f(r) 为奇数时,无解。

对于Easy version,

  • s u m r − s u m l − 1 = 0 sum_r-sum_{l-1}=0 sumrsuml1=0 则不用删除字符。
  • s u m r − s u m l − 1 sum_r-sum_{l-1} sumrsuml1 为奇数,根据 f ( i ) f(i) f(i) 的性质,必定存在 i i i 满足 s u m r − s u m i = s u m i − 1 − s u m l − 1 sum_r-sum_i=sum_{i-1}-sum_{l-1} sumrsumi=sumi1suml1 ,因此删除一个字符。
  • s u m r − s u m l − 1 sum_r-sum_{l-1} sumrsuml1 为偶数,则删除任意一个字符(例如 s l s_l sl )后即可转化为前一种问题。因此删除两个字符。

对于Hard version,
我们需要寻找满足 s u m r − s u m i = s u m i − 1 − s u m l − 1 sum_r-sum_i=sum_{i-1}-sum_{l-1} sumrsumi=sumi1suml1 i i i ,将式子变化为:
s u m r + s u m l − 1 = s u m i + s u m i − 1 sum_r+sum_{l-1}=sum_i+sum_{i-1} sumr+suml1=sumi+sumi1

因此可以将每个 i i i 放入 s u m i + s u m i − 1 sum_i+sum_{i-1} sumi+sumi1 的桶中统计,由于必定有解,因此查找时直接在对应桶中二分查找 [ l , r ] [l,r] [l,r] 区间内的 i i i 即可。

注意 s u m i + s u m i − 1 sum_i+sum_{i-1} sumi+sumi1 可能为负,因此需要加偏移量 B = 2 n B=2n B=2n

参考代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN=300300;
const int B=MAXN<<1;
char s[MAXN];
int sum[MAXN];
vector<int> vec[MAXN<<2];

int main()
{
	int T,n,q,i,l,r,dif,x,id;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&q);
		scanf("%s",s+1);
		for(i=B-2*n;i<=B+2*n;i++)
			vec[i].clear();
		for(i=1;i<=n;i++)
		{
			if(i&1)
				sum[i]=sum[i-1]+(s[i]=='+'?1:-1);
			else
				sum[i]=sum[i-1]-(s[i]=='+'?1:-1);
			vec[sum[i]+sum[i-1]+B].push_back(i);
		}
		while(q--)
		{
			scanf("%d%d",&l,&r);
			dif=sum[r]-sum[l-1];
			if(dif==0)
				printf("0\n");
			else
			{
				if(dif%2)
					printf("1\n");
				else
				{
					printf("2\n");
					printf("%d ",l);
					l++;
				}
				x=sum[r]+sum[l-1]+B;
				id=lower_bound(vec[x].begin(),vec[x].end(),l)-vec[x].begin();
				printf("%d\n",vec[x][id]);
			}
		}
	}
}

E. Rescue Niwen!

题目大意

定义长度为 n n n 的字符串 s s s 的扩展序列为 s 1 , s 1 s 2 , . . . , s 1 s 2 . . . s n , s 2 , s 2 s 3 , . . . , s 2 s 3 . . . s n , s 3 , s 3 s 4 , . . . s n − 1 s n , s n s_1,s_1s_2,...,s_1s_2...s_n,s_2,s_2s_3,...,s_2s_3...s_n,s_3,s_3s_4,...s_{n-1}s_n,s_n s1,s1s2,...,s1s2...sn,s2,s2s3,...,s2s3...sn,s3,s3s4,...sn1sn,sn 。例如字符串 ‘abcd’ 的扩展序列为 ‘a’,‘ab’,‘abc’,‘abcd’,‘b’,‘bc’,‘bcd’,‘c’,‘cd’,‘d’ 。

现在给定长度为 n ( 1 ≤ n ≤ 5000 ) n(1 \leq n \leq 5000) n(1n5000) 的字符串 s s s ,求其扩展序列的最长递增子序列长度。

题解

如果要快速比较扩展序列中两个字符串的大小,需要知道它们的最长公共前缀。
c i , j c_{i,j} ci,j 表示从 s i s_i si s j s_j sj 开始的两个后缀的最长公共前缀长度,易得
c i , j = { c i + 1 , j + 1 s i = s j 0 s i ≠ s j c_{i,j}=\begin{cases} c_{i+1,j+1} &s_i=s_j \\ 0 &s_i \neq s_j \end{cases} ci,j={ci+1,j+10si=sjsi=sj

设扩展序列中第 i i i 个字符串为 A i A_i Ai
i < j , A i < A j i<j,A_i<A_j i<j,Ai<Aj A i A_i Ai A j A_j Aj 的首字符在 s s s 中的来源并不相同,则包含 A i , A j A_i,A_j Ai,Aj 的最长递增子序列,必定也包含其他首字符与 A i A_i Ai 的相同,且长度比 A i A_i Ai 长的其他字符串。
例如 s = s= s=‘abcd’ ,若最长递增子序列包含 ‘b’ 与 ‘c’ ,则必定也包含 ‘bc’,‘bcd’ 。

d p i dp_i dpi 表示扩展序列中以首字符为 s i s_i si 的字符串结尾的最长递增子序列长度,则有
d p i = max ⁡ j = 1 i − 1 { d p j − c i , j ∣ s j + c i , j < s i + c i , j } + n − i + 1 dp_i=\max_{j=1}^{i-1}\{dp_j-c_{i,j}|s_{j+c_{i,j}}<s_{i+c_{i,j}}\}+n-i+1 dpi=j=1maxi1{dpjci,jsj+ci,j<si+ci,j}+ni+1

参考代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN=5050;
char s[MAXN];
int c[MAXN][MAXN],dp[MAXN];

int main()
{
	int T,n,ans,i,j;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%s",&n,s+1);
		for(i=n;i>=1;i--)
		{
			for(j=n;j>=1;j--)
			{
				if(s[i]==s[j])
					c[i][j]=c[i+1][j+1]+1;
				else
					c[i][j]=0;
			}
		}
		ans=0;
		for(i=1;i<=n;i++)
		{
			dp[i]=n-i+1;
			for(j=1;j<=i-1;j++)
			{
				if(dp[j]-c[i][j]+n-i+1>dp[i]&&s[j+c[i][j]]<s[i+c[i][j]])
					dp[i]=dp[j]-c[i][j]+n-i+1;
			}
			if(dp[i]>ans)
				ans=dp[i];
		}
		printf("%d\n",ans);
	}
}

F. Tubular Bells

题目大意

有一个长度为 n   ( 3 ≤ n ≤ 1 0 5 ) n~(3 \leq n \leq 10^5) n (3n105) 的包含 [ l , r ]   ( 1 ≤ l ≤ r ≤ 2 ⋅ 1 0 5 , r − l + 1 = n ) [l,r]~(1 \leq l \leq r \leq 2 \cdot 10^5,r-l+1=n) [l,r] (1lr2105,rl+1=n) 范围内所有数的序列 a a a ,你只知道 n n n ,但并不知道 l , r l,r l,r 。你需要通过交互问答猜测这个序列。

最多询问 n + 5000 n+5000 n+5000 次,每次询问输出两个正整数 x , y   ( 1 ≤ x ≤ y ≤ n , x ≠ y ) x,y~(1 \leq x \leq y\leq n,x\neq y) x,y (1xyn,x=y) ,系统会返回 l c m ( a x , a y ) lcm(a_x,a_y) lcm(ax,ay)

题解

n ( n − 1 ) 2 ≤ 5000 \frac{n(n-1)}{2}\leq 5000 2n(n1)5000 ,即 n ≤ 100 n\leq 100 n100 时,可以直接枚举所有 ( i , j ) (i,j) (i,j) 进行询问,设 c i , j c_{i,j} ci,j 表示询问 ( i , j ) (i,j) (i,j) 对的结果。
由于 g c d ( x , x + 1 ) = 1 gcd(x,x+1)=1 gcd(x,x+1)=1 ,因此 g c d ( x y , ( x + 1 ) y ) = 1 gcd(xy,(x+1)y)=1 gcd(xy,(x+1)y)=1
易得
a n s i = g c d j ≠ i { c i , j } ans_i=gcd_{j\neq i}\{c_{i,j}\} ansi=gcdj=i{ci,j}

特别注意的是,当 n = 3 n=3 n=3 时,对于中间值 y = l + 1 y=l+1 y=l+1 来说,不存在 x x x x + 1 x+1 x+1 使得 g c d ( x y , ( x + 1 ) y ) = 1 gcd(xy,(x+1)y)=1 gcd(xy,(x+1)y)=1

  • y = l + 1 y=l+1 y=l+1 为偶数,即 l l l 为奇数时, g c d ( l ( l + 1 ) , ( l + 2 ) ( l + 1 ) ) = l + 1 gcd(l(l+1),(l+2)(l+1))=l+1 gcd(l(l+1),(l+2)(l+1))=l+1 ,不影响结果。
  • y = l + 1 y=l+1 y=l+1 为奇数,即 l l l 为偶数时, g c d ( l ( l + 1 ) , ( l + 2 ) ( l + 1 ) ) = 2 ( l + 1 ) gcd(l(l+1),(l+2)(l+1))=2(l+1) gcd(l(l+1),(l+2)(l+1))=2(l+1) ,需要将其(最大值)除 2 2 2 才能得到正确答案。

n ( n − 1 ) 2 > 5000 \frac{n(n-1)}{2}> 5000 2n(n1)>5000 ,即 n > 100 n >100 n>100 时,若能找到在 ( l + r 2 , r ] (\frac{l+r}{2},r] (2l+r,r] 区间内的素数 p p p ,则易得 p p p [ l , r ] [l,r] [l,r] 范围内的其他数互质。

考虑随机化算法。
当范围越大时,素数出现概率越小,考虑最小的情况,即 l = 1 0 5 + 1 , r = 2 ⋅ 1 0 5 l=10^5+1,r=2\cdot 10^5 l=105+1,r=2105 ,其中 [ 150000 , 200000 ] [150000,200000] [150000,200000] 范围内共有 4136 4136 4136 个素数,占比 4.136 % 4.136\% 4.136%
因此可以任选 m = 250 m=250 m=250 个数,找出其中最大的素数,基本可以视为是 ( l + r 2 , r ] (\frac{l+r}{2},r] (2l+r,r] 区间内的素数。

对于任意一个数 y y y 来说,若能找到一对互质的数 x 1 , x 2 x_1,x_2 x1,x2
g c d ( l c m ( x 1 , y ) , l c m ( x 2 , y ) ) = y gcd(lcm(x_1,y),lcm(x_2,y))=y gcd(lcm(x1,y),lcm(x2,y))=y

根据黎曼猜想推导可得,任意两个自然数互质的概率是 6 π 2 ≈ 60 % \frac{6}{\pi^2}\approx 60\% π2660% ,是一个比较大的概率。
因此对于下标 u u u ,可以任选 k = 20 k=20 k=20 v i   ( u ≠ v i ) v_i ~(u \neq v_i) vi u=vi ,他们询问结果的 g c d gcd gcd 基本上就可以视为 a n s u ans_u ansu ,再查素数表即可知道其是否是素数。

由于是随机算法,具体 m m m k k k 的值需要调参,保证 m k ≤ 5000 mk \leq 5000 mk5000 即可。

参考代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MAXN=100100;
const int MAXM=200200;
int npri[MAXM];
ll ans[MAXN];

ll rd()
{
	return 1ll*rand()*RAND_MAX+rand();
}

ll gcd(ll x,ll y)
{
	return x%y?gcd(y,x%y):y;
}

ll lcm(ll x,ll y)
{
	return x*y/gcd(x,y);
}

ll query(int x,int y)
{
	cout<<"? "<<x<<" "<<y<<endl;
	ll ret;
	cin>>ret;
	return ret;
}

int main()
{
	int T,n,i,j,mx,id,mxid,m,u,v;
	ll g,c[110][110];
	ios::sync_with_stdio(false);
	cin.tie(0);
	for(i=2;i<MAXM;i++)
	{
		if(npri[i])
			continue;
		for(j=i+i;j<MAXM;j+=i)
			npri[j]=1;
	}
	cin>>T;
	while(T--)
	{
		cin>>n;
		if(n<=100)
		{
			for(i=1;i<=n;i++)
				for(j=i+1;j<=n;j++)
					c[i][j]=c[j][i]=query(i,j);
			for(i=1;i<=n;i++)
			{
				ans[i]=c[i][i%n+1];
				for(j=1;j<=n;j++)
				{
					if(i==j)
						continue;
					ans[i]=gcd(ans[i],c[i][j]); 
				}
			}
			if(n==3&&ans[1]%2==0&&ans[2]%2==0&&ans[3]%2==0)
			{
				mxid=1;
				for(i=1;i<=n;i++)
				{
					if(ans[mxid]<ans[i])
						mxid=i;
				}
				ans[mxid]/=2;
			}
		}
		else
		{
			m=250;
			mx=id=-1;
			while(m--)
			{
				u=rd()%n+1;
				g=0;
				for(i=0;i<20;i++)
				{
					v=rd()%n+1;
					while(u==v)
						v=rd()%n+1;
					if(g==0)
						g=query(u,v);
					else
						g=gcd(g,query(u,v));
				}
				if(!npri[g])
				{
					if(g>mx)
					{
						mx=g;
						id=u;
					}
				}
			} 
			for(i=1;i<=n;i++)
			{
				if(i==id)
					ans[i]=mx;
				else
					ans[i]=query(id,i)/mx;
			}
		}
		cout<<"!";
		for(i=1;i<=n;i++)
			cout<<" "<<ans[i];
		cout<<endl;
	}
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值