廣東工業大學新生賽決賽2017解題報告
阿新 • • 發佈:2018-11-12
A: junior97與The Flash
數學幾何題,對我這數學渣渣十分不友好。看的大佬的blog。問題的突破點在於,找到正n邊形的中心點到某一頂點的距離,根據這個距離,和中心與兩頂點所成交的弧度,就可以根據餘弦定理算出對角線長度。下面是中點到頂點的距離的求法,根據邊長為1和相鄰兩點與中點連線所成角用正弦或者餘弦定理可以求出中點到頂點的距離。
#include<cstdio> #include<cmath> using namespace std; #define pi 3.141592653 int t,n,m,a,b; double sum; int main() { scanf("%d",&t); while(t--) { b=1; sum=0; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d",&a); double x=(sin(pi/2-pi/n))/(sin(2*pi/n)); sum+=sqrt(2*x*x*(1-cos(2*pi*(a-b)/n))); b=a; } printf("%.5f\n",sum); } return 0; }
B: 狗哥的肚子
簡單的模擬
#include<cstdio> using namespace std; #define pi 3.14159 char ch; int t,n,a,b; double sum,maxn; int main() { scanf("%d",&t); while(t--) { maxn=0; scanf("%d",&n); getchar(); while(n--) { scanf("%c",&ch); if(ch=='C')scanf("%d",&a); else scanf("%d%d",&a,&b); getchar(); if(ch=='T')sum=(double)a*b/2; else if(ch=='R')sum=a*b; else sum=pi*a*a; if(sum>maxn)maxn=sum; } printf("%.2f\n",maxn); } return 0; }
C: 演算法的魅力
等差數列+容斥原理
#include<cstdio> using namespace std; int main() { int t,n;long long ans; scanf("%d",&t); while(t--) { scanf("%d",&n); ans=((long long )5+n-(n%5))*(n/5)/2+((long long )7+n-(n%7))*(n/7)/2; for(long long i=35,j=1;i<=n;j++,i=35*j)ans-=i; printf("%lld\n",ans); } return 0; }
D: Gakki的疑問
用字串存每一位的數字(0到9),每一次減的策略的每一位只要非0就減1,顯然,這樣做減的次數為最大的一個位數。這是看大佬的blog學到的,剛開始自己想的以數字儲存,每次減小於n的最大的01數,但遇到20的話,先減11,而非10,就出問題了。
#include<cstdio>
using namespace std;
int t,n;
int s[10],len;
int ans[10],num;
int pow(int num)
{
int ret=1;
while(num--)ret*=10;
return ret;
}
int main()
{
scanf("%d",&t);
while(t--)
{
len=0;
num=0;
scanf("%d",&n);
while(n)
{
s[len++]=n%10;
n/=10;
}
for(;;)
{
bool ok=1;
for(int i=0;i<len;i++)if(s[i]){ok=0;break;}
if(ok)break;
int ret=0;
for(int i=0;i<len;i++)
{
if(s[i])
{
s[i]-=1;
ret+=pow(i);
}
}
ans[num++]=ret;
}
printf("%d\n%d",num,ans[num-1]);
for(int i=num-2;i>=0;i--)printf(" %d",ans[i]);
putchar('\n');
}
return 0;
}
E: Joefery大佬的考核
又是數學幾何題,花了我好久才想出來。
#include<cstdio>
using namespace std;
int main()
{
int t,a,b;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&a,&b);
printf("%d\n",a*b%10007);
}
return 0;
}
F: 沒有題目背景的水題
裸的字首和
#include<cstdio>
using namespace std;
int main()
{
int t,a,b,n,k,num[5005];
scanf("%d",&t);
num[0]=0;
while(t--)
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d",&num[i]),num[i]+=num[i-1];
int i,j;
bool ok=0;
for(i=1;i<=n;i++)
{
for(j=i;j<=n;j++)
{
if(num[j]-num[i-1]==k){ok=1;break;}
}
if(ok)break;
}
printf("%d %d\n",i,j);
}
return 0;
}
G: 白色相簿的季節
錯排,剛學到的。
#include<cstdio>
using namespace std;
int main()
{
long long t,n,f[20];
f[1]=0;
f[2]=1;
for(int i=3;i<=18;i++)f[i]=(i-1)*(f[i-1]+f[i-2]);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
printf("%lld\n",f[n]);
}
return 0;
}
H: 最小公倍數
因為範圍很小,直接列舉這些數在1000內的公倍數,每訪問到一個,標記+1,最後從1開始看哪個數標記>=k。
#include<cstdio>
#include<cstring>
using namespace std;
int t,n,k,x;
int cnt[1001];
int main()
{
scanf("%d",&t);
while(t--)
{
memset(cnt,0,sizeof(cnt));
scanf("%d%d",&n,&k);
while(n--)
{
scanf("%d",&x);
for(int i=x;i<=1000;i+=x)cnt[i]++;
}
int i;
for( i=1;i<=1000;i++)if(cnt[i]>=k)break;
printf("%d\n",i);
}
return 0;
}
I: 狗哥的日常
不寫了。
J: csjhl和潮汕煎蠔烙
暴力法列舉每一個符號是加還是減。
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
int t,a[5],ans,sum;
scanf("%d",&t);
while(t--)
{
ans=0;
for(int i=0;i<5;i++)scanf("%d",&a[i]);
for(int i=0;i<(1<<5);i++)
{
if(!(1&i))continue;
sum=a[0];
for(int j=1;j<5;j++)if((1<<j)&i)sum+=a[j]; else sum-=a[j];
if(sum==24)ans++;
}
printf("%d\n",ans);
}
return 0;
}
K: 這題有點難
exgcd,由於不需要求x和y,所以只求gcd即可。存在xy條件是gcd(x,y)能整除c
#include<cstdio>
using namespace std;
void gcd(int a,int b,int& d,int& x,int& y)
{
if(!b){d=a;x=1;y=0;}
else
{
gcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
int main()
{
int t,a,b,q,d,x,y,c;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&a,&b,&q);
gcd(a,b,d,x,y);
for(int i=1;i<=q;i++)
{
scanf("%d",&c);
if(!(c%d))puts("Yes");
else puts("No");
}
}
return 0;
}