前情提要:
B题的结论到目前为止还没能推出来。
赛时七题,赛后补了C、E。
A 无关(relationship)
容斥原理dfs实现,注意剪枝否则爆long long
#include
#include
#include
#include
#include
#include
using namespace std;
#define LL unsigned long long
const int maxn = 1e2+3;
LL l,r,k;
LL a[maxn];
LL sum=0;
void dfs(LL x,LL now,LL c)
{
if(x>r) return;
if(c&1){
sum+=r/x-(l-1)/x;
}else{
sum-=r/x-(l-1)/x;
}
for(LL i=now+1;i<=k;i++){
dfs(x*a[i],i,c+1);
}
}
int main()
{
while(~scanf("%llu%llu%llu",&l,&r,&k)){
sum=0;
for(LL i=1;i<=k;i++)
scanf("%llu",&a[i]);
for(LL i=1;i<=k;i++)
dfs(a[i],i,1);
printf("%llu\n",(r-l+1)-sum);
}
}
B 范围(range)
还待解决,往大佬们不吝赐教。
#include
using namespace std;
int main() {
double A, B;
scanf("%lf%lf", &A, &B);
double L = (A - sqrt(2 * B - A * A)) / 2, R = (A + sqrt(2 * B - A * A)) / 2;
printf("%.2f %.2f", L, R);
}
C 水题(water)
分类讨论。
1.事前打表求出13之内的N皇后解。
2. f(i) f ( i ) 呈现斐波纳挈规律,所以可以打表查看x是否为斐波纳挈数。至于0的个数,可以通过对m分解质因数,然后枚举质因数的i次幂解决。
#include
using namespace std;
#define ll long long int
#define clr(x,y) memset(x,y,sizeof x)
const ll INF = 1e18;
int ans[15]= {0,1,0,0,2,10,4,40,92,352,724,2680,14200,73712,365596};
int pri[25]= { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
ll f[100];
ll cnt[100];
ll num[100];
void init();
int main()
{
clr(cnt,0);clr(num,0);
init();
ll x,m;
scanf("%lld %lld",&x,&m);
bool flag=0;
for(int i=1;i<=89;i++){
if(f[i]>x) break;
if(x==f[i]){
flag=1;break;
}
}
if(flag==1){
ll ans=INF;
int cs=0;
ll tmp=m;
for(int i=0;i<25;i++){
if(tmp==1) break;
if(tmp%pri[i]==0){
cnt[++cs]=pri[i];
while(tmp%pri[i]==0){
tmp/=pri[i];
num[cs]++;
}
}
}
if(tmp>1){
cnt[++cs]=tmp;
num[cs]++;
}
for(int i=1;i<=cs;i++){
tmp=0;
for(ll j=cnt[i];j<=x;j*=cnt[i])
tmp+=x/j;
ans=min(ans,tmp/num[i]);
}
printf("%lld\n",ans);
}
else{
ll z=x%(min(1ll*13,m))+1;
printf("%d\n",ans[z]);
}
return 0;
}
void init(){
f[1]=1;
f[2]=1;
for(int i=3;i<=99;i++){
f[i]=f[i-1]+f[i-2];
if(f[i]>=INF) break;
}
}
D 阶乘(factorial)
在单个阶乘内求末尾0的个数的基础上多了更多的考虑。突破口依然一样,盯住贡献量。
#include
using namespace std;
#define ll long long int
const int maxn=1e6+2333;
int main()
{ ll n;
scanf("%lld",&n);
if(n<=4) {
printf("0\n");
return 0;
}
ll ans=0, cnt=0;
ll tmp=0;int i;
for(i=5;i<=n;i+=5){
cnt++;
ll k=0;tmp=i;
while(tmp%5==0){
tmp/=5;
k++;
}
ans+=(n-i+1)*k;
}
printf("%lld\n",ans);
return 0;
}
E 面积(area)
题如其名,的确是面积问题。
点阵的最大生成图面积需要和三角形面积相等才可以剪裁拼接得到。
三角形面积:可以通过向量叉积求得;
点阵:通过观察每多一行或每多一列的图形变换,可以得到点阵的面积规律。
#include
using namespace std;
int main(){
std::ios::sync_with_stdio(false);
long long n,m,x1,x2,y1,y2;
double s1,s2;
while(cin>>n>>m){
cin>>x1>>y1>>x2>>y2;
s1=1.0*n/2.0*m-1;
s2=abs(x1*y2-x2*y1)/2.0;
if(s1==s2) cout<<"Yes\n";
else cout<<"No\n";
}
return 0;
}
F 圆(circle)
python秒?骗人的吧QAQ
查公式网站找到的规律ORZ
#include
#include
#include
using namespace std;
typedef long long int LL;
int main() {
LL n;
while(scanf("%lld",&n)!=EOF) {
printf("%lld\n",1+n*(n-1)/2+n*(n-1)*(n-2)*(n-3)/24);
}
return 0;
}
G 异或(xor)
直接看样例解释可以得到答案。
每三个数,前两个数是奇数,后一个是偶数。偶数不能吃。
#include
#include
using namespace std;
#define ll long long
int main()
{
ll n;
while(~scanf("%lld",&n)){
if(n%3==0){
printf("%lld\n",(n/3)*2);
}
else if(n%3==1){
printf("%lld\n",(n/3)*2+1);
}
else{
printf("%lld\n",(n/3)*2+2);
}
}
return 0;
}
H 最大公约数(lcm)
就是单纯的求最大公约数,注意要先除gcd再乘,否则爆炸。
#include
using namespace std;
const int maxn=1e5+45;
#define INF 0x3f3f3f3f;
#define ll unsigned long long
#define charmax(x,y) x=max(x,y)
#define charmin(x,y) x=min(x,y)
#define clr(x,p) memset(x,p,sizeof x)
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
int main()
{
ll a,b;
cin>>a>>b;
b=b/gcd(a,b);
cout<return 0;
}
I 区间 (interval)
线段树MLE;注意q的取值是0和非0而不是0和1;
因为只有一次查询,可以离线操作,和刚学树状数组遇到的气球染色问题类似。
#include
using namespace std;
#define ll long long int
const int maxn=1e6+2333;
int a[maxn];
int q[maxn];
int v[maxn];
int u[maxn];
int c[maxn];
int main(){
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
ll ans=0;
ll tmp=0;
int L,R;
for(int i=1;i<=m;i++)
{scanf("%d %d %d %d",&q[i],&u[i],&v[i],&c[i]);}
scanf("%d %d",&L,&R);
for(int i=L;i<=R;i++){
ans+=1ll*a[i];
}
// cout<for(int i=1;i<=m;i++){
tmp=0;
if(v[i]R) continue;
if(u[i]<=L){
if(v[i]>=R) tmp+=R-L+1;
else {
tmp+=v[i]-L+1;
}
}
else{
if(v[i]<=R) tmp+=v[i]-u[i]+1;
else{
tmp+=R-u[i]+1;
}
}
if(q[i]!=1) tmp=tmp*c[i];
else tmp=tmp*(-c[i]);
ans+=tmp;
}
printf("%lld\n",ans);
return 0;
}
J 时间(time)
这个题写法应该挺多的,我是打表二分找答案输出。
#include
using namespace std;
#define ll long long
const int maxn=1e5+20;
int a[maxn];
int ans[maxn];int x[maxn];int y[maxn];
int c[5];
int main()
{
int a,b;
char s;
cin>>a>>s>>b;int sz=0;
for(int i=0,j=0;;i++){
if(j>=24) break;
if(i==60) {
i=0;j++;
}
c[2]=j%10;c[1]=j/10;
c[3]=i/10;c[4]=i%10;
if(c[1]==c[4]&&c[2]==c[3]){
ans[++sz]=j*100+i;
x[sz]=j;y[sz]=i;
}
}
int p=a*100+b;
int pos=lower_bound(ans+1,ans+1+sz,p)-ans;
if(p&&p<=ans[pos]){
printf("%d:%d\n",x[pos-1],y[pos-1]);
}
else printf("%d:%d\n",x[sz],y[sz]);
pos=upper_bound(ans+1,ans+1+sz,p)-ans;
if(pos<=sz){
printf("%d:%d\n",x[pos],y[pos]);
}
else{
printf("%d:%d\n",x[1],y[1]);
}
return 0;
}