今天是一年一度的百度之星初赛的日子啊,大家都早早的准备好了比(上)赛(分),运气也不错,涨了不少分,rating到了2222(真尼玛2)
ps.我是开黑做的,所以这分数不代表真实水平,勿黑
给你一个由m个x组成的数字,模上k,问你是否等于c
k和c都小于10000,所以可以模拟,因为循环节不会大于10000,但是模拟很容易错,因为找到循环节的地方需要扣掉前面一段,然后各种XJB搞
模拟代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
#define MAX 100005
#define MAXN 6005
#define maxnode 15
#define sigma_size 30
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define middle int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem(x,v) memset(x,v,sizeof(x))
#define lowbit(x) (x&-x)
#define pii pair
#define bits(a) __builtin_popcount(a)
#define mk make_pair
#define limit 10000
//const int prime = 999983;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f;
const double pi = acos(-1.0);
//const double inf = 1e18;
const double eps = 1e-8;
const LL mod = 1e9+7;
const ull mx = 133333331;
/*****************************************************/
inline void RI(int &x) {
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/
int vis[10005];
int main(){
int t,kase=0;
cin>>t;
while(t--){
int x;
LL m;
int k,c;
cin>>x>>m>>k>>c;
int mo=0;
mem(vis,0);
int xun=INF;
int tmp;
for(int i=1;i<=m;i++){
mo=(mo*10+x)%k;
if(vis[mo]){
xun=i-vis[mo];
tmp=vis[mo];
break;
}
vis[mo]=i;
}
kase++;
printf("Case #%d:\n",kase);
if(xun==INF){
if(mo!=c) printf("No\n");
else printf("Yes\n");
}
else{
m=(m-tmp)%xun;
int mm=mo;
for(int i=0;i10+x)%k;
}
if(mm!=c) printf("No\n");
else printf("Yes\n");
}
}
return 0;
}
但是这题还有一种更加美妙的姿势,就是 xxx…x 这样m个x,除以x之后就是m个1,乘9之后就是m个9,加1之后就是 10m ,所以我们可以求出 10m−19×x(modk) ,判断其是否等于c,但是这样做前面需要快速幂,然后模k了之后就不能直接除以9,所以我们可以这样算 (10m−1)×x(mod9k)9 ,这样就可以愉快的快速幂运算了。
ps.还有人说可以用矩阵快速幂搞,貌似也是可以的呢
题意是给你n个数字,然后有些数字的位置已经固定,还有些数字的位置没有固定,让你给n个数字安排位置,使得相邻的数字的乘积和最大,有负数
首先需要记录,每个位置上是否有要求必须放第几个数
n最大范围是16,所以应该是状压,但是比赛时候我并不知道怎么dp,TAT
先确定状态 dp[i][j] ,i为这会哪些数字已经被选(二进制表示),j为最后一个选的数字是哪一个,比如i的二进制表示里面有k个1,表示1-k的位置上都已经放了数字了,j就是第k个位置上面放的数是原来数组里面的哪一个
(这个状态挺巧妙的感觉,我承认我确实没有想到,状压dp还是太渣了)
这样的话状态转移就很简单了辣
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
#define MAX 100005
#define MAXN 6005
#define maxnode 15
#define sigma_size 30
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define middle int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem(x,v) memset(x,v,sizeof(x))
#define lowbit(x) (x&-x)
#define pii pair
#define bits(a) __builtin_popcount(a)
#define mk make_pair
#define limit 10000
//const int prime = 999983;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f;
const double pi = acos(-1.0);
//const double inf = 1e18;
const double eps = 1e-8;
const LL mod = 1e9+7;
const ull mx = 133333331;
/*****************************************************/
inline void RI(int &x) {
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/
LL dp[1<<18][20];
int a[20];
int b[20];
int main(){
int t,kase=0;
cin>>t;
while(t--){
int n;
cin>>n;
mem(b,-1);
for(int i=0;i<(1<for(int j=0;j1e18;
}
for(int i=0;iint p;
scanf("%d%d",&a[i],&p);
if(p!=-1) b[p]=i;
}
if(b[0]!=-1) dp[(1<0])][b[0]]=0;
else for(int i=0;i1<0;
for(int i=1;i<(1<for(int j=0;jif(i&(1<for(int k=0;kif((i&(1<0){
int pos=bits(i);
if(b[pos]==k||b[pos]==-1){
dp[i|(1<1<1e18;
for(int i=0;i1<1][i]);
}
kase++;
printf("Case #%d:\n",kase);
cout<return 0;
}
这是一道很不错的树上的题目,给你n个点的树,然后每个点有权值,有两种操作,一种是把某个点的权值修改,另一种是求一条从0开始必须经过x点的路径,使得路径上的点权和最大
因为要至少走到x,甚至要走到x的子树上,所以我们考虑可以用dfs序来解这题,因为dfs序的特性,我们维护每个点到0点的距离,这样就能很快用线段树求出在x的子树上的一点,它到0点的权值和最大
因为点权有负数,所以我们dfs的时候,dfs序只能在进入的时候++,出来的时候就不要++了,这样可以去掉很多0的节点(我的dfs序还是很弱啊,本来准备复习下,结果比赛就考了)
有了dfs序和线段树就很容易辣呀,这样就更新的时候区间加和 y−a[x] ,然后 a[x]=y ,然后维护区间内最大值,就好啦
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
#define MAX 100005
#define MAXN 6005
#define maxnode 15
#define sigma_size 30
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define middle int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem(x,v) memset(x,v,sizeof(x))
#define lowbit(x) (x&-x)
#define pii pair
#define bits(a) __builtin_popcount(a)
#define mk make_pair
#define limit 10000
//const int prime = 999983;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f;
const double pi = acos(-1.0);
//const double inf = 1e18;
const double eps = 1e-8;
const LL mod = 1e9+7;
const ull mx = 133333331;
/*****************************************************/
inline void RI(int &x) {
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/
struct Edge{
int v,next;
}edge[MAX*2];
int head[MAX];
int tot;
int a[MAX];
int ti;
int p1[MAX];
int p2[MAX];
LL val[MAX];
void init(){
mem(head,-1);
mem(val,0);
tot=0;
ti=0;
}
void add_edge(int a,int b){
edge[tot].v=b;
edge[tot].next=head[a];
head[a]=tot++;
}
LL sum[MAX<<2];
LL col[MAX<<2];
void pushup(int rt){
sum[rt]=max(sum[lrt],sum[rrt]);
}
void build(int l,int r,int rt){
col[rt]=0;
if(l==r){
sum[rt]=val[l];
return;
}
middle;
build(lson);
build(rson);
pushup(rt);
}
void pushdown(int rt,int m){
if(col[rt]){
col[lrt]+=col[rt];
col[rrt]+=col[rt];
sum[lrt]+=col[rt];
sum[rrt]+=col[rt];
col[rt]=0;
}
}
void update(int l,int r,int rt,int L,int R,LL d){
if(L<=l&&r<=R) {
col[rt]+=d;
sum[rt]+=d;
return ;
}
middle;
if(col[rt]!=0) pushdown(rt,r-l+1);
if(L<=m) update(lson,L,R,d);
if(R>m) update(rson,L,R,d);
pushup(rt);
}
LL query(int l,int r,int rt,int L,int R){
if(L<=l&&r<=R) return sum[rt];
if(col[rt]) pushdown(rt,r-l+1);
middle;
LL ret=-1e18;
if(L<=m) ret=max(query(lson,L,R),ret);
if(R>m) ret=max(ret,query(rson,L,R));
return ret;
}
void dfs(int u,int fa,LL c){
p1[u]=++ti;
val[ti]=c;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue;
dfs(v,u,c+a[v]);
}
p2[u]=ti;
}
int main(){
int t,kase=0;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
init();
for(int i=1;iint x,y;
scanf("%d%d",&x,&y);
add_edge(x,y);
add_edge(y,x);
}
for(int i=0;iscanf("%d",&a[i]);
kase++;
printf("Case #%d:\n",kase);
dfs(0,-1,a[0]);
build(1,ti,1);
while(m--){
int op,x;
LL y;
scanf("%d%d",&op,&x);
if(op==0){
scanf("%I64d",&y);
update(1,ti,1,p1[x],p2[x],y-a[x]);
a[x]=y;
}
else printf("%I64d\n",query(1,ti,1,p1[x],p2[x]));
}
}
return 0;
}
额。。。不会
给你一个字符串的定义,就是里面有B也有D,然后有filp操作,就是把B变成D,D变成B,然后还有反向操作,就是把字符串倒置
然后问你在区间 [L,R] 之间有多少个B
第一反应这题肯定是求 solve(R)−solve(L−1)
然后就是怎么求1-x之间有多少个B的问题了,我们先打表找出,每个字符串k,它的长度len和里面含有的B的个数f,
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
#define MAX 205
#define MAXN 6005
#define maxnode 15
#define sigma_size 30
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define middle int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem(x,v) memset(x,v,sizeof(x))
#define lowbit(x) (x&-x)
#define pii pair
#define bits(a) __builtin_popcount(a)
#define mk make_pair
#define limit 10000
//const int prime = 999983;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-8;
const LL mod = 1e9+7;
const ull mx = 133333331;
/*****************************************************/
inline void RI(int &x) {
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/
LL f[70];
LL len[70];
void init(){
len[1]=1;
f[1]=1;
for(int i=2;;i++){
len[i]=len[i-1]*2+1;
f[i]=len[i-1]+1;
if(len[i]>=1e18) break;
}
}
LL solve(LL x){
if(x==0) return 0;
int k=1;
for(;;k++){
if(len[k]>x) break;
}
k--;
if(len[k]==x){
return f[k];
}
else return solve(2*len[k]-x+1)+x-len[k];
}
int main(){
//freopen("in.txt","r",stdin);
int t;
cin>>t;
init();
while(t--){
LL l,r;
scanf("%I64d%I64d",&l,&r);
printf("%I64d\n",solve(r)-solve(l-1));
}
return 0;
}
给你n个人的编号,编号就是他的值,然后排队,每次放进去一个人的时候可以加上一个值,这个值是他和他前面的所有人里面的最小值,但是有一些限制,就是有的人必须在有的人后面。求最后得到的和的最大值
首先我们考虑和要最大,那必须是大的人先放,再放小的,但是又有限制,就好比点的入度,就是一个点必须在另外个点的前面,拓扑序,所以我们可以模拟拓扑排序,把没有限制的点放进优先队列里,然后往外面取,每次取一个就接触它对别的点的限制,然后记录一个从第一个点到它的最小值就可以了
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
#define MAX 100005
#define MAXN 6005
#define maxnode 15
#define sigma_size 30
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define middle int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem(x,v) memset(x,v,sizeof(x))
#define lowbit(x) (x&-x)
#define pii pair
#define bits(a) __builtin_popcount(a)
#define mk make_pair
#define limit 10000
//const int prime = 999983;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f;
const double pi = acos(-1.0);
//const double inf = 1e18;
const double eps = 1e-8;
const LL mod = 1e9+7;
const ull mx = 133333331;
/*****************************************************/
inline void RI(int &x) {
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/
vector<int> v[MAX];
int deg[MAX];
int main(){
int t,kase=0;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) v[i].clear();
mem(deg,0);
for(int i=0;iint a,b;
scanf("%d%d",&a,&b);
v[a].push_back(b);
deg[b]++;
}
priority_queue<int> q;
for(int i=1;i<=n;i++){
if(deg[i]==0) q.push(i);
}
int mini=INF;
LL ans=0;
while(!q.empty()){
int x=q.top();q.pop();
mini=min(mini,x);
ans+=mini;
for(int i=0;iif(deg[v[x][i]]==0) q.push(v[x][i]);
}
}
cout<return 0;
}