IEEE Bigger系列题解

时间:2021-07-10 23:51:57

Bigger系列题解

Bigger Python

坑点在于要高精度以及表达式求值,用java写可以很容易避免高精度问题

然后这道题就可以AC了

代码

import java.io.*;
import java.util.*;
import java.math.*;
import java.text.*;

public class Main
{
static Map<String,BigInteger> map= new HashMap<String,BigInteger>();
static BigInteger cal(String s)
{
    BigInteger ans=BigInteger.ZERO,mu=BigInteger.ONE,tk,val;
    int tem,len=s.length(),la=1;
    for(int pos=0;pos<len;pos++)
    {
        if(s.charAt(pos)=='(')
        {
            int k=1;
            tk=BigInteger.ZERO;
            for(int d=pos+1;d<len;d++)
                if(s.charAt(d)=='(')
                    k++;
                else if(s.charAt(d)==')')
                {
                    k--;
                    if(k==0)
                    {
                        tk=cal(s.substring(pos+1,d));
                        pos=d+1;
                        break;
                    }
                }
        }
        else if(s.charAt(pos)=='-'||(s.charAt(pos)>='0'&&s.charAt(pos)<='9'))
        {
            int flag=1;
            if(s.charAt(pos)=='-'){flag=-1;pos++;}
            tem=0;
            while(pos<len&&s.charAt(pos)>='0'&&s.charAt(pos)<='9')
            {
                tem=tem*10+(s.charAt(pos)-'0');
                pos++;
            }
            tk=BigInteger.valueOf(tem*flag);
        }
        else
        {
            int fla=pos;
            while(pos<len&&((s.charAt(pos)>='a'&&s.charAt(pos)<='z')||(s.charAt(pos)>='A'&&s.charAt(pos)<='Z')))pos++;
            tk=map.get(s.substring(fla,pos));
        }
            if(pos==len)
            {
                mu=mu.multiply(tk);
                if(la==1)
                    ans=ans.add(mu);
                else
                    ans=ans.subtract(mu);
                return ans;
            }
            if(s.charAt(pos)=='+'||s.charAt(pos)=='-')
            {
                mu=mu.multiply(tk);
                if(la==1)
                    ans=ans.add(mu);
                else
                    ans=ans.subtract(mu);
                mu=BigInteger.ONE;
                if(s.charAt(pos)=='+')
                    la=1;
                else
                    la=0;
            }
            else if(s.charAt(pos)=='*')
                mu=mu.multiply(tk);
    } 
    return ans;
}
static void pr(String s)
{
    int pos,la=0,len=s.length();
    for(pos=0;pos<len;pos++)
    {
        if(s.charAt(pos)==',')
        {
            System.out.print(map.get(s.substring(la,pos)).toString()+" ");
            la=pos+1;
        }
    }
    System.out.println(map.get(s.substring(la,pos)).toString());
}
public static void main(String args[]) throws Exception
    {
        //Scanner in = new Scanner(new File("in.txt"));
        //PrintWriter out = new PrintWriter(new FileWriter("out.txt",true));

       Scanner in = new Scanner(System.in);
       String s,tem;
       char c;
       int len;
       int pos;
       map.clear();
       while(in.hasNext())
       {
           s=in.nextLine();
           tem="";
           len=s.length();            
           if(s.charAt(0)=='p')
               pr(s.substring(6, len-1));
           else
           {
               for(pos=0;pos<len;pos++)
                   if(s.charAt(pos)=='=')
                   {
                       map.put(s.substring(0,pos),cal(s.substring(pos+1, len)));
                   }
           }
       }       
         //System.out.println(h[n][m].mod(e));
        System.out.close();
       
    }
};

Bigger place

题源:ZOJ Monthly, December 2013 Problem H. Tragedy Organ
IEEE Bigger系列题解

IEEE Bigger系列题解

代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
using namespace std;

int main() {
  double x, e ,y;
  int t;
  scanf("%d",&t);
  while(t--)
  {
    cin>>x>>y;
    x = x / y * 25.0;
  x = sqrt(x * 0.04);
  e = 1 + 8.0 / sqrt(7.0) * sqrt(x) * sin(sqrt(7.0) / 2 * log(x));
  printf("%.12f\n", e);
  }
  return 0;
}

Bigger world

题目转化为{1,1,2,2,3,3,4,4,n,n}这个序列中,两个相同的数不挨在一起的方案数

用容斥什么的很容易就可以推出来公式了,然后显然不可以过,因为这道题的模数是一个非素数,所以得智障改一改公式,优化一下才行。

结果貌似大家都是on 递推的…

a(n) = n*(2*n-1)*a(n-1) + (n-1)*n*a(n-2)

代码

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

long long dp[100100];

int main(){
    int n,p;
    while(scanf("%d%d",&n,&p)!=EOF){
        n--;
        dp[2]=2%p;
        for(int i=3;i<=n;i++){
            dp[i]=1LL*i*(2*i-1)%p*dp[i-1]%p+1LL*(i-1)*i%p*dp[i-2]%p;
            dp[i]%=p;
        }
        printf("%lld\n",dp[n]);
    }
    return 0;
}

Bigger bet

随便推一推,发现这道题就是求行列式值,因为题目其实就是把行列式的定义说了一遍

然后这个怎么做呢?

定义消元后的f(i)=A[i][i]

很轻松就可以发现:f(n) = n^k - sigma(d|n)f(d),d<n,移项后 n^k = sigma(d|n)f(d)

f(i)显然是一个积性函数,f(p^a) = (p^k)^(a-1)(p^k-1),p是素数

然后线性筛就可以把f莽出来,这道题就结束了。

当然,这道题你得预处理+记忆化一些东西去优化常数。

代码

#include <cstdio>
#include <cstring>

const int MAXN = 1000000 + 10;
const int MOD = 1e9+7;

int vis[MAXN], A[MAXN];
int f[MAXN], p[MAXN], T, N, M, K, cas;

int pow_mod(int a, int n) {
  int ret = 1;
  for (; n; n >>= 1) {
    if (n & 1) ret = (long long)ret * a % MOD;
    a = (long long)a * a % MOD;
  }
  return ret;
}

void sieve() {
  M = 0;
  for (int i = 2; i < MAXN; ++ i) {
    if (!vis[i]) p[M ++] = i;
    for (int j = 0; j < M && i * p[j] < MAXN; ++ j) {
      vis[i * p[j]] = true;
      if (i % p[j] == 0) break;
    }
  }
}

int main() {
  sieve();
  scanf("%d", &T);
  for (cas = 1; cas <= T; ++ cas) {
    scanf("%d%d", &N, &K);
    K %= (MOD - 1);
    memset(f, 0, sizeof(int) * (N + 1)); f[1] = 1;
    for (int i = 2; i <= N; ++ i) {
      if (!f[i]) {
        A[i] = pow_mod(i, K), f[i] = A[i] - 1;
        if (f[i] < 0) f[i] += MOD;
      }
      for (int j = 0, t; j < M && (t = i * p[j]) <= N; ++ j) {
        if (i % p[j] == 0) {
          f[t] = (long long)f[i] * A[p[j]] % MOD;
          break;
        }
        else {
          f[t] = (long long)f[i] * (A[p[j]] - 1 + MOD) % MOD;
        }
      }
    }
    int ret = 1;
    for (int i = 1; i <= N; ++ i) ret = (long long)ret * f[i] % MOD;
    printf("%d\n", ret);
  }
  return 0;
}