Sums gym100753M
Sums gym100753M
同余最短路模板,然而这个东西貌似也可以做去年D1T2
首先我们选择一个模数作为基准,然后剩下的这样连边:
对于一个面值为 x 的硬币 ,当前在 u 这个点(感性理解一下吧)
u + x < Mod
这种情况直接从u向 u + x 连一条长度为0的边,表示我们在 0 * M + (u + x) 的时候就已经可以凑出了
u + x > Mod
这种情况下可以 u 向 ( u + x ) mod Mod 连一条长度为1的边,表示通过x的硬币至少在 1 * M + ( u + x ) 凑出。
直接dijk 复杂度会炸(但是可以用zkw线段树优化成 nlogm,就爆过去了)
然后如果Mod取硬币面值的最大值,那么这就是个01bfs,但是复杂度也是 O(n + M) 然而M是 n^2级别的
我们发现每个点只会考虑一次,所以我们可以用bitset优化这个bfs。具体而言,如果我们把 $ a[i] $ 存到一个bitset中,我们需要的转移是 $ trans $ 集体往左移动u次且循环移位后的trans。
学到了Bitset优化搜索这个套路233 但是由于需要提取1,还是得手写。。
这样优化就是 $ n + \frac{M}{w} $ 了
为了偷懒还是用类似dijk的bfs吧。。反正复杂度没问题
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
using namespace std;
//#define int long long
typedef long long ll;
#define MAXN 50006
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define inf 0x3f3f3f3f
#define cmx( a , b ) a = max( a , b )
#define cmn( a , b ) a = min( a , b )
void read( int& x ) {
scanf("%d",&x);
}
void read( ll& x ) {
scanf("%lld",&x);
}
int n , q;
int A[MAXN] , mx;
struct Bitset
{
unsigned a[1600];
void reset()
{
memset(a,0,sizeof(a));
}
Bitset()
{
reset();
}
void flip(int x)
{
a[x>>5]^=1<<(x&31);
}
void set(int x)
{
a[x>>5]|=1<<(x&31);
}
void reset(int x)
{
a[x>>5]&=~(1<<(x&31));
}
int test(int x)
{
return (a[x>>5]>>(x&31))&1;
}
Bitset operator ~()const
{
Bitset ret;
for(int i=0;i<1600;i++)ret.a[i]=~a[i];
return ret;
}
Bitset operator &(const Bitset &b)const
{
Bitset ret;
for(int i=0;i<1600;i++)ret.a[i]=a[i]&b.a[i];
return ret;
}
Bitset operator |(const Bitset &b)const
{
Bitset ret;
for(int i=0;i<1600;i++)ret.a[i]=a[i]|b.a[i];
return ret;
}
Bitset operator ^(const Bitset &b)const
{
Bitset ret;
for(int i=0;i<1600;i++)ret.a[i]=a[i]^b.a[i];
return ret;
}
Bitset operator <<(const int t)const
{
Bitset ret;
unsigned last=0;
int high=t>>5,low=t&31;
for(int i=0;i+high<1600;i++)
{
ret.a[i+high]=last|(a[i]<<low);
if(low)last=a[i]>>(32-low);
}
return ret;
}
Bitset operator >>(const int t)const
{
Bitset ret;
unsigned last=0;
int high=t>>5,low=t&31;
for(int i=1600-1;i>=high;i--)
{
ret.a[i-high]=last|(a[i]>>low);
if(low)last=a[i]<<(32-low);
}
return ret;
}
vector<int> ones()const
{
vector<int> ret;
for(int i=0;i<1600;i++)
{
unsigned tmp=a[i];
while(tmp)
{
short t=__builtin_ctz(tmp);
ret.pb((i<<5)|t);
tmp^=1u<<t;
}
}
return ret;
}
}use,trans;
int dis[MAXN];
priority_queue< pii , vector<pii> , greater<pii> > Q;
vector<int> cur;
void bfs( ) {
memset( dis , 0x3f , sizeof dis );
Q.push( mp( 0 , 0 ) ); dis[0] = 0;
while( !Q.empty() ) {
int u = Q.top().se; Q.pop( );
cur = ( ( ( trans << u ) | ( trans >> ( mx - u ) ) ) & use ).ones( );
for( auto& v : cur ) {
if( v < u )
dis[v] = dis[u] + 1 , Q.push( mp( dis[v] , v ) ) , use.reset( v );
else
dis[v] = dis[u] , Q.push( mp( dis[v] , v ) ) , use.reset( v );
}
}
}
int main() {
read( n );
for( int i = 1 ; i <= n ; ++ i )
read( A[i] ) , mx = max( mx , A[i] );
for( int i = 1 ; i <= n ; ++ i ) trans.set( A[i] );
for( int i = 0 ; i <= mx ; ++ i ) use.set( i );
bfs();
read( q );
int x;
while( q --> 0 ) {
read( x );
int a = x % mx , b = x / mx;
puts( ( dis[a] == 0x3f3f3f3f || dis[a] > b ) ? "NIE" : "TAK" );
}
}
/*
* Things you should pay attention to
* inf is big enough?
* out of bounds?
* long long ?
*/
Sums gym100753M的更多相关文章
- 正睿OI国庆DAY2:图论专题
正睿OI国庆DAY2:图论专题 dfs/例题 判断无向图之间是否存在至少三条点不相交的简单路径 一个想法是最大流(后来说可以做,但是是多项式时间做法 旁边GavinZheng神仙在谈最小生成树 陈主力 ...
- [LeetCode] Find K Pairs with Smallest Sums 找和最小的K对数字
You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k. Define ...
- UVA-11997 K Smallest Sums
UVA - 11997 K Smallest Sums Time Limit: 1000MS Memory Limit: Unknown 64bit IO Format: %lld & ...
- POJ3187Backward Digit Sums[杨辉三角]
Backward Digit Sums Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6350 Accepted: 36 ...
- Leetcode Find K Pairs with smallest sums
本题的特点在于两个list nums1和nums2都是已经排序好的.本题如果把所有的(i, j)组合都排序出来,再取其中最小的K个.其实靠后的很多组合根本用不到,所以效率较低,会导致算法超时.为了简便 ...
- SPOJ TSUM Triple Sums(FFT + 容斥)
题目 Source http://www.spoj.com/problems/TSUM/ Description You're given a sequence s of N distinct int ...
- ural 2065. Different Sums
2065. Different Sums Time limit: 1.0 secondMemory limit: 64 MB Alex is a very serious mathematician ...
- codeforces 477A A. Dreamoon and Sums(数学)
题目链接: A. Dreamoon and Sums time limit per test 1.5 seconds memory limit per test 256 megabytes input ...
- [codeforces 509]C. Sums of Digits
[codeforces 509]C. Sums of Digits 试题描述 Vasya had a strictly increasing sequence of positive integers ...
随机推荐
- javascript-jquery对象的其他处理
一.对元素进行遍历操作 如果要遍历一个jquery对象,对其中每个匹配元素进行相应处理,那么可以使用each()方法. $("div").each(function(index,e ...
- Egg.js学习与实战系列 · 文件上传配置
在使用Egg.js搭建文件上传服务时,遇到了几个一般新手都会遇到的坑. 经查阅官方文档,Egg框架中默认使用egg-multipart插件进行文件上传,所以上传文件前需要做相关的配置. 上传文件提示: ...
- CodeForces-1076E Vasya and a Tree
CodeForces - 1076E Problem Description: Vasya has a tree consisting of n vertices with root in verte ...
- 单片机stm32的5个时钟源的详细分析
众所周知STM32有5个时钟源HSI.HSE.LSI.LSE.PLL,其实他只有四个,因为从上图中可以看到PLL都是由HSI或HSE提供的. 其中,高速时钟(HSE和HSI)提供给芯片主体的主时钟.低 ...
- linux中的分号 && ||
几个符号的用法 ; 顺序地独立执行各条命令, 彼此之间不关心是否失败, 所有命令都会执行. && 顺序执行各条命令, 只有当前一个执行成功时候, 才执行后面的. & 放在启动参 ...
- palindrome-partitioning-ii leetcode C++
Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...
- poj 2724 Purifying Machine(二分图最大匹配)
题意: 有2^N块奶酪,编号为00...0到11..1. 有一台机器,有N个开关.每个开关可以置0或置1,或者置*.但是规定N个开关中最多只能有一个开关置*. 一旦打开机器的开关,机器将根据N个开关的 ...
- swagger3.0(springboot)消除basic-error-controller
1.新建springboot项目,可以通过https://start.spring.io/快速生成springboot项目. 2.引入jar依赖: <dependency> <gro ...
- java随手记 面向对象
// 可以把两个类放在同一个文件中,但文件中只能有一个类是公共类,且公共类必须与文件同名,即xxx.java,源代码中的每个类编译成class文件 // java库中的类 // java.util.* ...
- MySQL 默认隔离级别是RR,为什么阿里这种大厂会改成RC?
我之前写过一篇文章<为什么MySQL选择REPEATABLE READ作为默认隔离级别?>介绍过MySQL 的默认隔离级别是 Repeatable Reads以及背后的原因. 主要是因为M ...