问题虫洞——D:Big Integer
黑洞内窥:
给出t组样例,每组输入p,n,m,有函数A(n) = n个1,如A(2) = 11, A(5) = 11111, 问有多少对(i,j)使得
光年之外:
前面一块的思路感觉是蛮清晰的,后面这么看着看着就有点模糊了。。。。。。
推荐博客:D.Big Integer(费马小定理+找循环节)
代码块:
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f//将近ll类型最大数的一半,而且乘2不会爆ll
const ll mod = 100000000;
const int MAXN = 200005;
ll t, n, m, p;
ll pi[105], ai[105], cnt, tot;
//ll gcd(ll a, ll b){return b==0? a: gcd(b, a%b);}
ll ksm(ll a, ll b, ll c)
{
ll ans=1;
while(b)
{
if(b&1)
ans = ans*a%c;
a = a*a%c;
b>>=1;
}
return ans;
}
int main()
{
scanf("%lld", &t);
while(t--)
{
pi[0]=0, cnt=0, tot=0;
scanf("%lld %lld %lld", &p, &n, &m);
if(p == 2 || p == 5)
{
puts("0");
continue;
}
ll y=p-1, x=p;
if(p==3) //最小的循环节为3
x=3;
else
{ //求最小循环节
for(ll i=2; i*i<=y; ++i)
if(y%i == 0)
if(ksm(10, i, p) == 1)
x = min(x, i);
else if(ksm(10, y/i, p) == 1)
x = min(x, y/i);
if(ksm(10, p-1, p) == 1)
x = min(x, p-1);
}
for(ll i=2; i*i<=x; ++i)//记录质因子和个数,pi[0]用来统计总个数
if(x%i == 0)
{
pi[++pi[0]] = i;
ai[pi[0]] = 0;
while(x%i == 0)
{
x/=i;
++ai[pi[0]];
}
}
if(x > 1)
{
pi[++pi[0]] = x;
ai[pi[0]] = 1;
}
ll maxn=0, ans=0;
for(ll i=1; i<=pi[0]; ++i)
maxn = max(maxn, ai[i]);
for(ll i=1; i<=min(maxn, m); ++i)//按[(质因子每个)/i]回代求g,再ans+=(每个g的贡献)
{
ll pre = 1;
for(ll cc, j=1; j<=pi[0]; ++j)
{
cc = ai[j]/i + (ai[j]%i!=0);
while(cc--)
pre*=pi[j];
}
ans+=n/pre;
}
if(m > maxn) //不再贡献
{
ll pre = 1;
for(ll i=1; i<=pi[0]; ++i)
pre*=pi[i];
ans+=1ll*(m-maxn)*(n/pre);
}
printf("%lld\n", ans);
}
return 0;
}
问题虫洞——F:Planting Trees
黑洞内窥:
给你一个n*n的矩阵, 要你求出最大子矩阵的面积
子矩阵满足最大值和最小值的差值小于等于k.
光年之外:
首先先将二维矩阵压缩成一维的状态
枚举上界和下界的值,将每一列的最大值和最小值记录下来
然后开两个单调队列来记录当前最大值和最小值的位置
最大值单调递减,最小值单调递增
枚举右边界 每次记录下最大的面积
(然而我并不会丫丫丫丫!!!!)
代码块:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f//将近ll类型最大数的一半,而且乘2不会爆ll
const ll mod = 1000000007;
const int MAXN = 511;
int a[MAXN][MAXN], mxx[MAXN], mii[MAXN], q[MAXN][2], n, k, t;
int main()
{
cin >> t;
while(t--)
{
scanf("%d %d", &n, &k);
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
scanf("%d", &a[i][j]);
int ans = 1;
for(int i=1; i<=n; ++i)
{
for(int j=1; j<=n; ++j)
{
mxx[j] = -mod;
mii[j] = mod;
}
for(int j=i; j<=n; ++j)
{
for(int k=1; k<=n; ++k)
{
mxx[k] = max(mxx[k], a[j][k]);
mii[k] = min(mii[k], a[j][k]);
}
int l=1, h0=0, t0=1, h1=0, t1=1;
for(int r=1; r<=n; ++r)
{
while(t0 <= h0 && mxx[r] >= mxx[q[h0][0]]) h0--;
while(t1 <= h1 && mii[r] <= mii[q[h1][1]]) h1--;
q[++h0][0] = r;
q[++h1][1] = r;
while(l<=r && mxx[q[t0][0]] - mii[q[t1][1]] > k)
{
l++;
if(q[t0][0] < l) t0++;
if(q[t1][1] < l) t1++;
}
ans = max(ans, (r-l+1)*(j-i+1));
}
}
}
cout << ans << '\n';
}
return 0;
}
问题虫洞——H:Magic Line
黑洞内窥:
有t组样例,每组样例给出n个坐标,且n为偶数,n<=1000,
求一条将n个点平分的直线,并输出该直线上的任意两点。
光年之外:
按照x,y排序一遍,在中点坐标做一条极度倾斜的直线即可,(注意y的值不能相同)
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f//将近ll类型最大数的一半,而且乘2不会爆ll
const ll mod = 100000000;
const int MAXN = 200005;
struct node
{
ll x, y;
} stu[MAXN];
ll cmp(node a, node b)
{
if(a.x == b.x)
return a.y > b.y;
return a.x < b.x;
}
int main()
{
ll n, t;
scanf("%lld", &t);
while(t--)
{
scanf("%lld", &n);
for(int i=1; i<=n; ++i)
scanf("%lld%lld", &stu[i].x, &stu[i].y);
sort(stu+1, stu+n+1, cmp);
printf("%lld %lld %lld %lld\n", stu[n/2].x-1, stu[n/2].y-mod-1, stu[n/2].x+1, stu[n/2].y+mod);
}//注意这里的两处y要相差1,是为了避免过那个点,,,
return 0;
}