Блог пользователя Felix_Mate

Автор Felix_Mate, история, 5 лет назад, По-русски
Hi all!
I have a problem with the task.
Give me hint how to solve or tell me about my mistake
F(N, K) = amount of numbers x from 1 to N such that x<=K (lexicographically)
Q(N, p) = amount of numbers x from 1 to N such that x = p* where * is some sequence of numbers (may be empty)
My algo is binary search by N:
F(N, K) <= F(N+1, K) and find such N that F(N, K) = M
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;


#define ll unsigned long long
const ll inf = 18446744073709551615;
           
ll K, M;

vector<int> to_vec(ll X);
ll F(ll N, ll K);
ll F(ll N, ll K);
ll Q(ll N, ll pref, int len);
ll deg[20];


int main()
{
    deg[0] = (ll)1;
    for(int i=1;i<20;i++)
         deg[i] = deg[i-1] * (ll)10;
    cin>>K>>M;
    

    
    ll L = K, R = inf;
    while(R-L>1)
    {
    		 ll r1 = L%2, r2 = R%2;
    		 ll m = L/2 + R/2;
    		 if(r1==1 && r2==1)
    			m+=(ll)1;
             if(F(m, K)<=M) L=m;
             else R=m;
    }
    
    if(F(L,K)==M) cout<<L;
    else
    {
             if(F(L+1,K)==M) cout<<L+1;
             else cout<<"0";
    }

    
    return 0;
}



vector<int> to_vec(ll X)
{
         vector<int> res;
         do
         {
                  res.push_back(X % 10);
                  X/=10;
         }
         while(X > 0);
         reverse(res.begin(),res.end()); 
         return res;
}


ll Q(ll N, ll pref, int len)
{
   ll res = (ll)0;
   vector<int> n = to_vec(N);    
   if (len > n.size() || len == n.size() && pref > N)
         return (ll)0;
   else
   {
            if(len == n.size()) 
                  return (ll)1;
            else
            {
                  ll nr = N / deg[n.size() - len];
                  if(pref > nr)
                           return res;
                  if(pref == nr)
                  {
                           res += (deg[n.size() - len] - (ll)1) / (ll)9;
                           return res + N % deg[n.size() - len] + 1;
                  }
                  return  res += (deg[n.size() - len + 1] - (ll)1) / (ll)9;
            }
   }
}


ll F(ll N, ll K)
{
   if(K == 0) return (ll)0;
   ll res = (ll)1;
   vector<int> k = to_vec(K);
   vector<int> n = to_vec(N);
   for(int q=1;q<k[0];q++) res+=Q(N, q, 1);
   for(int r=0;r<k.size()-1;r++)
   {
            ll pref = (ll)0;
            for(int j=0;j<=r;j++)
                  pref = ((ll)10 * pref) + (ll)k[j];
            res += (ll)1;
            for(int q=0;q<k[r+1];q++)
            {
                  res+=Q(N, pref * (ll)10 + (ll)q, r + 2);   
            }
   }
   return res;
}

Полный текст и комментарии »

  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

Автор Felix_Mate, история, 6 лет назад, По-русски

Получаю ВА1 в тренировке: 2012-2013 Тренировка СПбГУ B #17 Строки (по материалам контеста Сергея Копелиовича)

Код (суффмассив украл с e-maxx):

include

using namespace std;

const int maxlen = 1000 * 1005; const int alphabet = 256;

int n; int p[maxlen], cnt[maxlen], c[maxlen]; int pn[maxlen], cn[maxlen], lcp[maxlen]; char s[maxlen];

int main() { FILE * fp = fopen("suffarray.in", "r"); n = 0; while (fscanf(fp, "%c", &s[n]) != EOF) n++; s[++n] = char(0); fclose(fp);

memset(cnt, 0, alphabet * sizeof(int));
for (int i = 0; i<n; ++i) ++cnt[s[i]];
for (int i = 1; i<alphabet; ++i) cnt[i] += cnt[i - 1];
for (int i = 0; i<n; ++i) p[--cnt[s[i]]] = i;
c[p[0]] = 0;
int classes = 1;
for (int i = 1; i<n; ++i)
{
    if (s[p[i]] != s[p[i - 1]])  ++classes;
    c[p[i]] = classes - 1;
}

for (int h = 0; (1 << h)<n; ++h)
{
    for (int i = 0; i<n; ++i)
    {
       pn[i] = p[i] - (1 << h);
       if (pn[i] < 0)  pn[i] += n;
    }
    memset(cnt, 0, classes * sizeof(int));
    for (int i = 0; i<n; ++i) ++cnt[c[pn[i]]];
    for (int i = 1; i<classes; ++i) cnt[i] += cnt[i - 1];
    for (int i = n - 1; i >= 0; --i) p[--cnt[c[pn[i]]]] = pn[i];
    cn[p[0]] = 0;
    classes = 1;
    for (int i = 1; i<n; ++i)
    {
       int mid1 = (p[i] + (1 << h)) % n, mid2 = (p[i - 1] + (1 << h)) % n;
       if (c[p[i]] != c[p[i - 1]] || c[mid1] != c[mid2]) ++classes;
       cn[p[i]] = classes - 1;
    }
    memcpy(c, cn, n * sizeof(int));
}

n--;
fp = fopen("suffarray.out", "w");

for (int i = 0; i < n; i++) p[i] = p[i + 1];

for (int i = 0; i<n-1; i++) fprintf(fp, "%d ", p[i] + 1);
fprintf(fp, "%d", p[n-1] + 1);
fclose(fp);

return 0;

}

Полный текст и комментарии »

  • Проголосовать: нравится
  • -39
  • Проголосовать: не нравится

Автор Felix_Mate, история, 6 лет назад, По-русски

Хотелось бы узнать решение 2-х задач с тимуса

1)http://acm.timus.ru/problem.aspx?space=1&num=1677 Знаю, как её решать неоптимально (проблемы с ML, но не с TL). Можно получить точную дробь-ответ в длинной арифметике. У нас цепь маркова, переходы задаются с помощью граней префикса строки, состояния- префиксы длины 0,1,2,...n=len(s). Переход из состояния i в состояние j происходит с P=1/A (A-мощность алфавита), i<n и с P=1 из n в n. Можно написать соответствующие матожидания и получить СЛАУ. Решать СЛАУ можно за O(n), введя коэффициенты a[i],b[i] и с начального значения их пересчитывать. Проблема возникает с тем, что они быстро растут и потому ML. Код: https://ideone.com/41LFtk

2)http://acm.timus.ru/problem.aspx?space=1&num=1849 Думаю, что мой алгоритм верный, но где-то кроется баг (скорее всего в модулярной арифметике). Вначале утверждение: пусть есть прямая l x=xo+ut, y=yo+vt. Тогда точка x,y принадлежит l <=> xv-yu=xo*v-yo*u. Отсюда сделаем предпосчёт: фиксируем всевозможные направления векторов стрельбы vx,vy и каждой точке xk,yk сопоставим 2 числа:(e,t), где e=xk*v-yk*u и t=xk,если u=0, иначе t=yk. Получим класс cl[u][v]: {e1,t1}, {e2,t2}, ... , {en,tn}, который отсортируем по e, а при равных e по t. Теперь, получая луч (xo,yo,u,v), можно за O(logn) найти все точки лежащие на этой прямой (прямой, а не луче): нужны те точки, у которых e=xo*v-yo*u. Бинпоиском найдём в классе cl[u][v] границы alpha и beta. Среди этих точек нужны те, которые лежат на луче. Тут возможны случаи: если луч наклонный (например v>0), то тогда нужны точки с ординатой >= yo-ищем на [alpha, beta] бинпоиском по t, если луч горизонтальный (например u>0), то тогда нужны точки с абсциссой >= xo-ищем на [alpha, beta] бинпоиском по t (др. 2 случая аналогичны). Код: https://ideone.com/0Fm1CG

Полный текст и комментарии »

  • Проголосовать: нравится
  • +5
  • Проголосовать: не нравится

Автор Felix_Mate, история, 6 лет назад, По-русски

Хотелось бы узнать решения задач

http://acm.timus.ru/problem.aspx?space=1&num=1890

http://acm.timus.ru/problem.aspx?space=1&num=1839

http://acm.timus.ru/problem.aspx?space=1&num=2022

http://acm.timus.ru/problem.aspx?space=1&num=1655

везде имею WA

1890 решаю так: строю HLD; имею 2 дерева отрезков: для суммы прибавок в департаментах (до корня) (с запросами изменить значение элемента и найти сумму на отрезке) и для суммы всех индивидуальных прибавок сотрудникам в корне с заданной вершиной (с запросами найти суммарную прибавку в элементе и прибавить значение на отрезок). есть подозрения, что плохо считываю данные или имею переполнение типов код(WA2): https://ideone.com/fork/hprg2R

1839 решаю так: перебираю дуги и для каждой ищу рожицы: во-первых отсеим все неподходящие точки без условия 4); получим претендентов Pret; теперь проблема только с условием 4). Рассмотрим очередную точку Х из Pret; для неё нужно найти все такие Y из Pret, что cos(YRP)<cos(XRP) и cos(YPR)>cos(XPR); это можно сделать за логарифм для каждой точки Х с помощью ДО. Код(WA3): https://ideone.com/fork/HmAhfk

2022 решаю так:пусть T-момент прыжка; до него движение описывается так: x(t)=vx * t, y(t)=vy * t — g*t*t/2; чтобы прыжок можно было совершить, необходимы условия: x(T)<L, y(T)>0, T>0, откуда получаем интервал для T; далее полёт описывается так: x(t')=x(T) + (vx+ux) * t', y(t')=y(T) + (vy-g*T+uy)*t' — g*t'*t'/2; теперь необходимые условия пролёта через дырку выглядят так: в момент пролёта t1 через стену (т.е. когда x(t1)=x(T)+(vx+ux)*t1=L) в т. L нужно h<y(t1)<h+d, в момент пролёта t2 через стену (т.е. когда x(t2)=x(T)+(vx+ux)*t2=L+l) в т. L+l нужно h<y(t2)<h+d, (3) а также если максимальная высота ф-ии y(t') достигается на [t1, t2], то max(t')<h+d. В итоге получаем некоторые интервалы решений (возникающие при решении неравенств), их пересекаем; потом (если выполняется (3), то некоторые из них обрезаем. Ответ=середина интервала длины не меньше 0.000001 Код(WA3) : писать не буду, т.к. сдавал без (3), а с (3) даже инпут не прохожу.

1655 решаю так: пишу ДП: dp[i][j][0]-минимальное время уничтожения кораблей на [i,j], если мы находимся в позиции i (где находится i корабль), dp[i][j][1]-минимальное время уничтожения кораблей на [i,j], если мы находимся в позиции j (где находится j корабль). Особо пояснять нечего. Единственное, в реализации вместо делений на скорость я все числа умножал на неё. Код (WA8):https://ideone.com/GPQRO8

Полный текст и комментарии »

  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

Автор Felix_Mate, история, 7 лет назад, По-русски

Долго думал над этими задачами,в итоге так и не решил их. Хотелось бы узнать возможные идеи решений.

1) http://acm.timus.ru/problem.aspx?space=1&num=1872 Решаю так. Во-первых, жадно ищу решение: сортирую s[]-размер офисов, на каждом шаге делаю срезки отрезков [ai,bi] по s[i] и среди полученных отрезков выбираю для s[i] отрезок с наименьшей длиной. Этому отрезку k ставлю в соответствие s[i]: inv[k]=i. Во-вторых, если решение есть, проверяю единственность: строю орграф g[][]. Для каждого s[i] ищу те отрезки j, где aj<=s[i]<=bj и inv[j]!=i (каждому отрезку соответствует офис inv[j]). Если условия выполнены=> g[i][inv[j]]=true. В-третьих, поверяю наличие цикла в g[][]: он существует <=> решение не единственно.

Код с WA29:

const int nmax = 1005;

int a[nmax], b[nmax], s[nmax], inv[nmax];
int aa[nmax], bb[nmax], cl[nmax];
bool used[nmax];
bool g[nmax][nmax];
int n, cycle_st;

void QSort(int L, int R);
bool Exist();
bool dfs (int v);

int main()
{ cin>>n; for(int i=1;i<=n;i++) cin>>s[i]; QSort(1, n); for(int i=1;i<=n;i++) cin>>a[i]>>b[i];

if(Exist())
{
   for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
         g[i][j]=false;

   for(int i=1;i<=n;i++)
   {
      for(int j=1;j<=n;j++)
      {
         if(inv[j]==i) continue;
         g[i][inv[j]]=(a[j]<=s[i] && s[i]<=b[j]);
      }
   }

  for(int i=1;i<=n;i++) cl[i]=0;
   cycle_st = -1;
   for (int i=1; i<=n; i++)
       if (dfs(i)) break;

  if (cycle_st!=-1) cout<<"Ask Shiftman for help.";
   else
   {
         cout<<"Perfect!"<<endl;
         for(int i=1;i<=n;i++) cout<<inv[i]<<" ";
   }
}
else cout<<"Let's search for another office.";

return 0;

}

bool Exist()
{
for(int i=1;i<=n;i++) used[i]=false;
for(int i=1;i<=n;i++) aa[i]=a[i], bb[i]=b[i];

for(int i=1;i<=n;i++)
{
int k=-1;
for(int j=1;j<=n;j++)
{
if(used[j]) continue;
if(bb[j]<s[i]) return false;
if(aa[j]<s[i]) aa[j]=s[i];
if(aa[j]==s[i] && (k==-1 || bb[k]>bb[j])) k=j;
}
if(k==-1) return false;
used[k]=true;
inv[k]=i; //k->s[i]
}
return true;
}

bool dfs (int v)
{
cl[v] = 1;
for (int j=1; j<=n; j++)
{
int to = j;
if(!g[v][j]) continue;
if (cl[to] == 0)
{
if (dfs (to)) return true;
}
else if (cl[to] == 1)
{
cycle_st = to;
return true;
}
}
cl[v] = 2;
return false;
}

void QSort(int L, int R)
{
int X=s[(L+R)/2];
int i=L, j=R;
while(i<=j)
{
while(s[i]<X) i++;
while(s[j]>X) j--;
if(i<=j)
{
int Y=s[i]; s[i]=s[j]; s[j]=Y;
i++, j--;
}
}
if(L<j) QSort(L,j);
if(i<R) QSort(i,R);
}

2)http://acm.timus.ru/problem.aspx?space=1&num=2055 Решать не решился, поскольку нет ясных мыслей. Насколько понимаю, для начало нужно отсортировать рёбра, затем найти минимальное остовное дерево. Затем на каждом шаге выбрасывать ребро наименьшего веса и вновь искать минимальное остовное дерево(с рёбрами, у которых вес >= веса выброшенного ребра). Непонятно, можно ли быстро искать новое остовное дерево, если уже большая часть была построена.

Полный текст и комментарии »

  • Проголосовать: нравится
  • -20
  • Проголосовать: не нравится