牛客挑战赛60题解A-C
A题:第三心脏

由gcd的性质,我们可以得到:
设gcd(a,b)=x;
a=k*x;
b=t*x;
c=w*x;
且k,t,w三个数互质
因为c是a的倍数:w=n*k;(n>=2)
所以c=n*k*x;
现在需要使得gcd(b,c)即gcd(t*x,n*k*x)=x;
也就是说要让gcd(t,n*k)=1;
即 t 和 n*k 互质
因为k 和 t 互质
所以只需要n和t互质即可
所以就for(n=2;;n++)
直到gcd(n,t)==1;
输出n*k*x;
1 #include"bits/stdc++.h" 2 using namespace std; 3 #define int long long 4 int gcd(int a,int b){ 5 return b==0?a:gcd(b,a%b); 6 } 7 signed main(void){ 8 int t;cin>>t; 9 while(t--){ 10 int a,b; 11 scanf("%lld%lld",&a,&b); 12 int gg=gcd(a,b); 13 int k=a/gg; 14 int t=b/gg; 15 int w; 16 for(int i=2;;i++){ 17 w=i*k; 18 if(gcd(w,t)==1){ 19 break; 20 } 21 } 22 printf("%lld\n",w*gg); 23 24 } 25 return 0; 26 }
B题:尖端放电

一开始就觉得暴力枚举每两个尖塔的时间复杂度O(k^2) 都10的10次方了,肯定是不行的。。。
结果可以。。。
那就很简单了,枚举所有两个尖塔,得到中点。(还是觉得很奇怪这都能过??)
1 #include"bits/stdc++.h" 2 using namespace std; 3 #define maxn 100010 4 inline int read() 5 { 6 int x = 0;char c = getchar(); 7 while (c < '0' || c>'9') c = getchar(); 8 while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); 9 return x; 10 } 11 struct xy{ 12 int x; 13 int y; 14 }a[maxn]; 15 map<pair<double,double>,int>ump; 16 int main(void){ 17 int t;cin>>t; 18 while(t--){ 19 int n,m,k; 20 cin>>n>>m>>k; 21 for(int i=1;i<=k;i++){ 22 cin>>a[i].x>>a[i].y; 23 // a[i].x=read();a[i].y=read(); 24 } 25 int flag=0; 26 for(int i=1;i<=k;i++){ 27 for(int j=i+1;j<=k;j++){ 28 double xx,yy; 29 xx=((double)a[i].x+(double)a[j].x)/2; 30 yy=((double)a[i].y+(double)a[j].y)/2; 31 pair<double,double>temp;temp.first=xx;temp.second=yy; 32 ump[temp]++; 33 if(ump[temp]>=2){ 34 printf("YES %.1lf %.1lf\n",xx,yy); 35 flag=1; 36 break; 37 } 38 } 39 if(flag)break; 40 } 41 if(flag==0)printf("NO\n"); 42 ump.clear(); 43 } 44 return 0; 45 }
c题:格点染色
 

考虑函数dp(x)代表前x格的全部染成黑色的顺序种类
1.当前x-1的格子都染黑了,在前x的格子中最后染色的是第x格时候,因为此时只有一种选择,故:dp(x)=dp(x-1)
2.接下来,我们由1.大概能知道,这题对 每个dp(x)需要由dp(x-1)推导出,所以考虑dp(x-1)和dp(x)的关系。
考虑一般的dp(x-1)到dp(x)是走到x-1格子,然后走到下一格x,将其染色,完成操作。
但是我们可不可以在原先【染dp(x-1)】的【最后一个格子p】的步骤时候,选择不去染,然后先去染x格,然后再跳回来,【最后染第p个格子】呢?(为了理解局限为最后一个格子p)
***因为染完x,我们会跳到小于x的ax格子去,所以如果p属于[ax,x-1]区间,我们就可以由p的前一个染色的格子y 所跳 ay开始走,走过p,走到x,然后染色,跳到ax,再继续走到p的时候,以p作为dp(x)的最后一个染色格子,完成dp(x)的操作。
其中路径:
y<=x-1
ay<=p;
p: [ax,x-1]
从左至右数轴的点(其中一种可行的方法,并不止这一种):ay,ax,y,p,x-1,x
各位可以以上面的路径点画出dp(x-1)的运行操作,然后利用上述操作,完成dp(x)的操作,会很清晰。
扩展推广一下,其实p点并不局限为最后一个染色点,可以手动模拟试试。
在原先染dp(x-1)的方案的基础上,对每个方案,都对最后一次染色改变选择,所以dp(x)是由每个dp(x-1)的可能性基础上,然后选择某个点p,p点只要属于[ax,x-1]即可。故此时在原先的基础上,多了x-1-ax+1种选择可能,故dp(x)=dp(x-1)*(x-1-ax+1)
综上两种可能,我们可以得到dp(x)=dp(x-1)*(x-1-ax+1)+dp(x-1)=dp(x-1)*(x-ax+1)。
由此得到res*=(i-ai+1) , i:[1,n]。
时间复杂度O(n)
1 #include<iostream> 2 using namespace std; 3 const int mod=1e9+7; 4 int main(void){ 5 int n; 6 cin>>n; 7 long long res=1; 8 for(int i=1;i<=n;i++){ 9 long long x;scanf("%lld",&x); 10 x=i-x+1; 11 res=(x*res)%mod; 12 } 13 cout<<res<<endl; 14 return 0; 15 }
任重道远
                    
                
                
            
        
浙公网安备 33010602011771号