弱弱的DXY
题目描述
DXY太弱了,以至于他已经不知道要如何解决调整一个数列的使得他变成一个严格上升序列。
输入格式
第 1 行,1 个整数 N
第 2 行,N 个整数 A1,A2,...,AN
输出格式
1 个整数,表示最少需要修改的多少个数字,使得数列变成单调上升的序列。
样例输入
3
1 3 2
样例输出
1
数据:
对于50%的数据:N<=1000
对于100%的数据:N<=100000
保证所有输入整数<=2^63-1
由于数据比较弱所以可以直接写成最长上升子序列然后n-f[n]骗骗分(大雾)
正解的话是把位置i上的数字减去i,做不下降子序列就好了,不过普通dp会T要找nlogn的做法QAQ
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 #define LiangJiaJun main 8 #define INF 1999122700 9 using namespace std; 10 int a[100004]; 11 int unset[100004],n; 12 int cnt=0; 13 int erfen(int x){ 14 int l=0,r=n,ans=0; 15 while(l<=r){ 16 int mid = (l+r) >> 1; 17 if(unset[mid]>x)r=mid-1; 18 else{ 19 ans = mid; 20 l = mid + 1; 21 } 22 } 23 return ans; 24 } 25 int LiangJiaJun(){ 26 freopen("loser.in","r",stdin);freopen("loser.out","w",stdout); 27 scanf("%d",&n); 28 for(int i=1;i<=n;i++){ 29 scanf("%d",&a[i]); 30 a[i]-=i; 31 } 32 for(int i=0;i<=n+1;i++)unset[i]=INF; 33 unset[1]=a[1];unset[0]=-INF; 34 for(int i=2;i<=n;i++){ 35 int x=erfen(a[i])+1; 36 unset[x]=min(a[i],unset[x]); 37 } 38 for(int i=1;i<=n;i++)if(unset[i]!=INF)cnt=i; 39 cout<<n-cnt<<endl; 40 fclose(stdin);fclose(stdout); 41 return 0; 42 }hint:
不减i的话你看看这个数据1 2 3 2 2 2 2 4 5
减去i如果是不下降就说明那些在不下降序列上的数已经符合他们在数列中的位置,不需要修改了
数学(math.cpp)
DXY的数学很差。。。
对于所有1<=i<=N求(2^i – i^2)能被7整除的个数。(N<=1000000)
样例输入:
3
样例输出:
1
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #define LiangJiaJun main 5 using namespace std; 6 int kk[4]={2,4,1},ans=0;long long n; 7 int LiangJiaJun(){ 8 cin>>n; 9 for(long long i=1;i<=n;i++){ 10 long long x=( kk[ (i-1)%3LL ] + 7LL - ((i*i)%7LL) ) %7LL ; 11 // cout<<i<<" "<<(i-1)%3<<" "<<((1<<i))%7<<" "<<kk[ (i-1)%3LL ]<<endl; 12 if(x==0){ 13 ++ans; 14 } 15 } 16 cout<<ans<<endl; 17 return 0; 18 }考虑到N可能很大,模拟一下2^i的情况,可以得到kk数组
+7LL有两个点
1.7默认是int,LL后缀默认long long不会溢出
2.7防止取余出现负数
由于都是对7取模,我们可以分步取模
发现2^i对7取模有规律,只要i^2对7取模与其相等就得解
面包(bread.cpp)
DXY想在一些城市之间开一家面包店。
面包店必须要和小麦店连通,但是这些城市中有小麦店的城市只有K个,很坑的是DXY不喜欢在有小麦店的城市开面包店。一共有n个城市,m条双向路径,K个城市有小麦店。求面包店和小麦店的最短距离是多少。(不能开店的话输出-1)
第一行:n,m,k
第二行到第m+1行,m条路径,u,v,w(表示从u城市到v城市有一条长度为w的边)
第三行一共k个数,表示有小麦店的城市的编号。
样例:
输入:
5 4 2
1 2 5
1 2 3
2 3 4
1 4 10
1 5
输出:
3
输入:
3 1 1
1 2 3
3
输出:
-1
代码
枚举每一条边(其实枚举小麦店的边就可以),检查是否成立,得到最小值,还要什么超时的最短路
只考虑一条边的原因,1条边+1条边>1条边的长度
上个 @萌萌的代码
![]()
画风太萌不敢看1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define maxn 100005 7 #define qaq 2000022800 8 using namespace std; 9 10 int ans=qaq; 11 int n,m,k;//<=100000 12 int xiaomai; 13 int f[maxn]; 14 int QAQ[maxn][3]; 15 16 int main() 17 { 18 memset(f,0,sizeof(f)); 19 cin>>n>>m>>k; 20 for(int i=1;i<=m;++i) 21 { 22 scanf("%d%d%d",&QAQ[i][0],&QAQ[i][1],&QAQ[i][2]);//A B W 23 } 24 for(int i=1;i<=k;++i) 25 { 26 scanf("%d",&xiaomai); 27 f[xiaomai]=1; 28 } 29 for(int i=1;i<=m;++i) 30 { 31 if(f[QAQ[i][0]]!=f[QAQ[i][1]]) 32 { 33 ans=min(ans,QAQ[i][2]); 34 } 35 } 36 if(ans==qaq)puts("-1"); 37 else printf("%d\n",ans); 38 return 0; 39 }
孪生蜘蛛
http://codevs.cn/problem/1020/
代码详见这里:http://www.cnblogs.com/radiumlrb/p/5823169.html
间隙妖怪(gap.cpp/c/pas)
题目描述:
八云紫是幻想乡的间隙妖怪。她喜欢和八云橙玩一个叫做翻转的游戏。具体规则如下,八云紫对一个长度为N字符串做M次翻转操作,每次操作给定一个X,八云紫将X到N-X之间的字符串翻转。她最喜欢的就是在做M次操作之前询问八云橙这个字符串会变成什么样。然而愚钝的橙一般是答不出来的。为了让橙不在紫妈面前丢脸,你能够帮帮她吗?
输入数据:
第一行:一个字符串(即原字符串)
第二行:一个整数M,表示有M次操作
第三行:M个整数,表示每次操作的X
输出数据:
一个字符串,表示M次操作之后的字符串。
输入样例:
abcdef
1
2
输出样例:
aedcbf
数据范围:
对于50%数据:M<=5000,字符串长度<=5000
对于100%数据:M<=200000,字符串长度<=200000
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #define inf 0x3f3f3f3f 6 using namespace std; 7 int len,n,a[300005]; 8 //n<1 ??? 9 char s[300005],p[300005]; 10 int main(){ 11 freopen("gap.in","r",stdin);freopen("gap.out","w",stdout); 12 scanf("%s",s+1); 13 len=strlen(s+1); 14 scanf("%d",&n); 15 for(int i=1;i<=len;i++)p[i]=s[i]; 16 for(int i=1;i<=n;i++){ 17 int x; 18 scanf("%d",&x); 19 x=min(x,len-x+1); 20 a[x]++; 21 } 22 int q=0; 23 for(int i=1;i<=len/2+1;i++){ 24 q+=a[i]; 25 if(q%2==0){ 26 s[i]=p[i]; 27 s[len-i+1]=p[len-i+1]; 28 } 29 else{ 30 s[i]=p[len-i+1]; 31 s[len-i+1]=p[i]; 32 } 33 } 34 for(int i=1;i<=len;i++)printf("%c",s[i]); 35 printf("\n"); 36 fclose(stdin); 37 fclose(stdout); 38 return 0; 39 }两次反转就不用重复反转
![]()
错误代码1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #define inf 0x3f3f3f3f 6 using namespace std; 7 int len,n,luo[300005],a[300005]; 8 //n<1 ??? 9 char str[300005]; 10 int main(){ 11 freopen("gap.in","r",stdin); 12 freopen("gap.out","w",stdout); 13 scanf("%s",str+1); 14 len=strlen(str+1); 15 scanf("%d",&n); 16 if(n<1) { 17 for(int i=1;i<=len;i++) printf("%c",str[i]); 18 puts(""); 19 return 0; 20 } 21 22 for(int i=1;i<=n;i++){ 23 int x=1; 24 scanf("%d",&x); 25 26 if(luo[x]==0) luo[x]=1;//两次的不用重复计算 27 else luo[x]=0; 28 } 29 30 for(int i=1;i<=n/2;i++){//应该为i<=len/2 31 if(luo[i]==1&&luo[len-i+1]==1) luo[i]=luo[len-i+1]=0;//左右两次的不用重复计算 32 if(luo[i]==0&&luo[len-i+1]==1) swap(luo[i],luo[len-i+1]);//都归到数组左边 33 } 34 35 //想不到好算法 36 int point=1; 37 while(point<=len/2){//标记需要交换的元素 38 if(luo[point]==1){ 39 int i=point+1;//如果该元素需要标记,则向右扫, 40 //直到右边出现需要交换的首位 ,将该首位置零 41 while(i<=len/2){ 42 if(luo[i]==1){ 43 luo[i]=0; 44 break; 45 } 46 else luo[i]=1; 47 point=i++; 48 } 49 } 50 point++; 51 } 52 53 for(int i=1;i<=len/2;i++) 54 if(luo[i]==1) 55 swap(str[i],str[len-i+1]); 56 57 for(int i=1;i<=len;i++) printf("%c",str[i]);//out 58 puts(""); 59 return 0; 60 }命名规范一点儿,Line30致命错误
无聊的gcd(gcd.c/cpp/pas)
话说出题人不会被查水表吧。
简单的问题描述:从N个正整数里面取出K个数的最大公因数最小是多少。(请将答案乘上k之后输出哦,谢谢合作。)
输入格式
第一行两个正整数N,K。
第二行n个正整数
输出格式
输出一个正整数表示最大的最大公因数。
样例输入
3 1
1 2 3
样例输出
3
数据说明
对于30%的数据,保证k≤n≤20。
对于50%的数据,保证输入中所有数小于5000。
对于100%的数据,保证输入中所有数小于500000,k≤n。
代码
![]()
不会1 #include <cstdio> 2 #include<iostream> 3 using namespace std; 4 const int Maxn = 40; 5 6 int a[Maxn],n,k,ans=0; 7 8 int gcd(int a,int b) 9 { 10 return b ? gcd(b,a%b) : a; 11 } 12 13 int max(int a,int b) 14 { 15 return a < b ? b : a ; 16 } 17 18 int main() 19 { 20 scanf("%d%d",&n,&k); 21 for(int i=0;i<n;++i)scanf("%d",&a[i]);//读入 22 for(int i=1;i<(1<<n);++i) 23 { 24 int tmp = 0; 25 for(int j=0;j<n;++j) 26 { 27 if(i&(1<<j)) ++tmp; 28 //tmp表示选了几个数 29 } 30 // printf("i = %d : tmp = %d\n",i,tmp); 31 if(tmp==k)//如果选了k个 32 { 33 tmp=-1; 34 for(int j=0;j<n;++j) 35 { 36 if(i&(1<<j)) 37 { 38 if(tmp==-1) tmp=a[j]; 39 else tmp=gcd(a[j],tmp); 40 } 41 } 42 ans = max(ans,tmp); 43 // printf("ans : %d\n",ans); 44 } 45 } 46 printf("%d",ans*k); 47 puts(""); 48 return 0; 49 }转载@gc812
0表示不取 1表示取
用i的二进制表示状态 比如i=10101表示取1,3,5 i=00110表示取3,4
然后for一遍,tmp表示i的二进制当中1的数量
如果1有k个
那么i代表的状态选了k个数for一遍把i表示的状态取了的数的gcd取出来
最后统计ans如果i&(1<<j) == 1的话那么i的第j位就是1
因为1<<j是...001000...的形式存在,所以和 i 与起来,要是 i 这一位是 1 , 就是1,i 这一位是0,就是0
所以 i&(1<<j) 表示 i 在二进制下的第 j 位
因为1<<0 = 1 这时候j=0 如果从1存的话就变成1<<1 = 2 那就时间复杂度*2 所以从0开始读
因为所有输入的数字都不超过五十万
那么我们就可以开个数组t,记一下每个数字出现的次数
然后枚举答案
判断一个答案是否可行的方法就是遍历t数组
看看所有答案x的倍数的个数是否大于等于k
虫洞(wormhole.cpp/c/pas) http://poj.org/problem?id=3259
【题目描述】
John在他的农场中闲逛时发现了许多虫洞。虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前)。John的每个农场有M条小路(无向边)连接着N (从1..N标号)块地,并有W个虫洞(有向边)。其中1<=N<=500,1<=M<=2500,1<=W<=200。 现在John想借助这些虫洞来回到过去(出发时刻之前),请你告诉他能办到吗。 John将向你提供F(1<=F<=5)个农场的地图。没有小路会耗费你超过10000秒的时间,当然也没有虫洞回帮你回到超过10000秒以前。
【输入格式】
* Line 1: 一个整数 F, 表示农场个数。
* Line 1 of each farm: 三个整数 N, M, W。
* Lines 2..M+1 of each farm: 三个数(S, E, T)。表示在标号为S的地与标号为E的地中间有一条用时T秒的小路。
* Lines M+2..M+W+1 of each farm: 三个数(S, E, T)。表示在标号为S的地与标号为E的地中间有一条可以使John到达T秒前的虫洞。
【输出格式】
* Lines 1..F: 如果John能在这个农场实现他的目标,输出"YES",否则输出"NO"。
【样例输入】
2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8
【样例输出】
NO
YES
代码
![]()
Dijkstra错误代码#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<vector> using namespace std; struct city{ int num,d,magic; }nod[505];//存 magic虫洞 单向边 city make_city(int num,int d,int magic){ city a;a.num=num;a.magic=magic;a.d=d; return a; } struct cmp{ bool operator()(city a,city b){ return a.d>b.d; } }; priority_queue<city,vector<city>,cmp > que; vector<int> e[505],c[505]; int dis[505],vis[505],n,m,w; void cls(){ for(int i=1;i<=503;i++){ e[i].clear(); c[i].clear(); nod[i].d=0; nod[i].magic=0; nod[i].num=i; } n=m=w=0; memset(vis,0,sizeof(vis)); priority_queue<city,vector<city>,cmp > temp; swap(que,temp); } void Dijkstra(){ memset(dis,0x3f,sizeof(dis)); que.push(make_city(1,0,nod[1].magic));dis[1]=0; while(!que.empty()){ city now=que.top();que.pop(); if(vis[now.num]) continue;vis[now.num]=1; if(now.magic>dis[now.num]){ puts("YES");return; } for(int i=0;i<e[now.num].size();i++){ if(dis[now.num]+c[now.num][i]<dis[e[now.num][i]]){ dis[e[now.num][i]]=dis[now.num]+c[now.num][i]; que.push(make_city(e[now.num][i],dis[e[now.num][i]],nod[e[now.num][i]].magic)); } } } puts("NO");return; } int main(){ // freopen("wormhole.in","r",stdin); // freopen("wormhole.out","w",stdout); int shu=0; scanf("%d",&shu); for(int bian=1;bian<=shu;bian++){ cls(); scanf("%d%d%d",&n,&m,&w); for(int i=1;i<=m;i++){ int u=0,v=0,cost=0; scanf("%d%d%d",&u,&v,&cost); e[v].push_back(u); e[u].push_back(v); c[u].push_back(cost); c[v].push_back(cost); } for(int i=1;i<=w;i++){ int u=0,v=0,cost=0; scanf("%d%d%d",&u,&v,&cost); nod[u].magic=cost;//单向边 } Dijkstra(); } return 0; }//题意是任意顶点都可以出发1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #define INF 0x3f3f3f3f 6 using namespace std; 7 struct edge{int from,to,cost;}e[6005]; 8 int N,M,W,p,d[505]; 9 10 int find_negative_loop(int V,int E){ 11 memset(d,0x3f,sizeof(d)); 12 13 for(int i=1;i<=V;i++){ 14 for(int j=1;j<=E;j++){ 15 edge now=e[j]; 16 17 if(d[now.to]>d[now.from]+now.cost){ 18 d[now.to]=d[now.from]+now.cost; 19 if(i==V) return 1; 20 } 21 22 } 23 } 24 return 0; 25 } 26 27 void add(int from,int to,int cost){ 28 e[++p].from=from; 29 e[p].to=to; 30 e[p].cost=cost; 31 } 32 33 void cls(){ 34 for(int i=0;i<=6002;i++){ 35 e[i].from=e[i].to=e[i].cost=0; 36 } 37 p=0; 38 N=M=W=0; 39 } 40 41 int main(){ 42 // freopen("wormhole.in","r",stdin); 43 // freopen("wormhole.out","w",stdiout); 44 int kk; 45 scanf("%d",&kk); 46 while(kk--){ 47 cls(); 48 49 scanf("%d%d%d",&N,&M,&W); 50 for(int i=1;i<=M;i++){ 51 int u,v,w; 52 scanf("%d%d%d",&u,&v,&w); 53 add(u,v,w); 54 add(v,u,w); 55 } 56 57 for(int i=1;i<=W;i++){ 58 int u,v,w; 59 scanf("%d%d%d",&u,&v,&w); 60 add(u,v,-w); 61 } 62 63 if(find_negative_loop(N,p)) puts("YES"); 64 else puts("NO"); 65 } 66 return 0; 67 }题意是找负环~
![]()
转载SPFA#include <iostream> #include <cstdio> #include <vector> #include <stack> using namespace std; #define inf 99999999 #define V 520 #define NE 6000 int n,m,w; struct node { int v; int val; }E; vector<node> Node[V+2]; int spfa(int k) { int d[V], cnt[V], vis[V]; for(int j = 1;j <= n;j ++) d[j] = inf,cnt[j] = 0,vis[j] = 0; d[k] = 0; vis[k] = 1;cnt[k] = 1; stack<int> p;p.push(k); while(!p.empty()) { int u = p.top(); p.pop();vis[u] = 0; int len = Node[u].size(); for(int j = 0;j < len;j ++) { int v = Node[u][j].v; int c=Node[u][j].val; if(d[v] - c > d[u]) { d[v] = c + d[u]; if(!vis[v]) { vis[v] = 1; cnt[v] ++; if(cnt[v] >= n) return 1; p.push(v); } } } } return 0; } int main() { int cs; scanf("%d",&cs); while(cs--) { scanf("%d%d%d",&n,&m,&w); for(int j = 1;j <= n;j ++) Node[j].clear(); while(m--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); E.v = b; E.val = c; Node[a].push_back(E); E.v = a; E.val = c; Node[b].push_back(E); } while(w--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); E.v = b;E.val = -c; Node[a].push_back(E); } if(!spfa(1)) puts("NO"); else puts("YES"); } return 0; }注意边可能很多,要开到6000才压得住
5*2500而不是2500,我zz了
a*b(mod.cpp/c/pas)
没错dxy的题目就是这么简单。
输入:
第一行一个数t,表示有t个数据
第2到第t+1行,每行三个正整数a,b,c (a,b,c<=10^18)
输出:对于每组数据输出(a*b)%c
样例输入:
1
1 2 3
样例输出:
2
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 int a[20002],b[20002],c[20002],d[20002],e[20002],k[20002]; 8 int l1,l2,l3,i,code; 9 int n; 10 string n1,n2; 11 12 void init(int a[]) { 13 string s; 14 int i; 15 memset(a,0,sizeof(a)); 16 cin >> s; 17 a[0] = s.length(); 18 for(i=1;i<=a[0];i++) { 19 a[i]=s[a[0]-i]-48; 20 } 21 } 22 23 void print(int a[]) { 24 int i; 25 for(int i=a[0]; i>=1; i--) cout << a[i]; 26 puts(""); 27 } 28 29 void clear(int a[]) { 30 int i; 31 for(int i=1;i<=a[0];i++) { 32 a[i+1]+=a[i]/10; 33 a[i]%=10; 34 } 35 while((a[a[0]]==0) && (a[0]>1)) a[0]--; 36 } 37 38 int compare(int a[], int b[]) { 39 int i; 40 clear(a); 41 clear(b); 42 if(a[0]>b[0]) { 43 return 1; 44 } 45 if(a[0]<b[0]) { 46 return -1; 47 } 48 for(i=a[0]; i>=1; i--) { 49 if(a[i]>b[i]) { 50 return 1; 51 } 52 if(a[i]<b[i]) { 53 return -1; 54 } 55 } 56 return 0; 57 } 58 59 60 void minus1(int a[], int b[], int c[]) { 61 int i; 62 int t[20002]; 63 bool flag = false; 64 if(compare(a,b)<0) { 65 memcpy(c,b,sizeof(c)); 66 memcpy(t,b,sizeof(t)); 67 memcpy(b,a,sizeof(b)); 68 flag = true; 69 } else memcpy(c,a,sizeof(int)*20002); 70 for(i=1;i<=c[0];i++) { 71 c[i+1]--; 72 c[i]+=10-b[i]; 73 } 74 clear(c); 75 if(flag) memcpy(b,t,sizeof(b)); 76 } 77 78 void multiply(int a[], int b[], int c[]) { 79 int i,j; 80 memset(c, 0, sizeof(int)*20002); 81 for(i=1; i<=a[0];i++) 82 for(j=1;j<=b[0];j++) 83 c[i+j-1]+=a[i]*b[j]; 84 c[0]=a[0]+b[0]; 85 clear(c); 86 } 87 88 void divide(int a[], int b[], int c[],int d[]) { 89 int i,j,p; 90 memset(c, 0, sizeof(c)); 91 memset(d, 0, sizeof(d)); 92 c[0]=a[0]; d[0]=1; 93 for(j=a[0]; j>=1;j--) { 94 d[0]++; 95 for(p=d[0];p>=2;p--) { 96 d[p]=d[p-1]; 97 } 98 d[1]=a[j]; 99 while(compare(d,b)>=0) { 100 c[j]++; 101 minus1(d,b,d); 102 } 103 } 104 clear(c); 105 clear(d); 106 } 107 108 int main() { 109 freopen("mod.in","r",stdin); 110 freopen("mod.out","w",stdout); 111 scanf("%d",&n); 112 while(n--){ 113 memset(a,0,sizeof(a)); 114 memset(b,0,sizeof(b)); 115 memset(c,0,sizeof(c)); 116 memset(d,0,sizeof(d)); 117 memset(e,0,sizeof(e)); 118 memset(k,0,sizeof(k)); 119 120 init(a); 121 init(b); 122 init(k); 123 multiply(a,b,e); 124 divide(e,k,c,d); 125 print(d); 126 } 127 return 0; 128 }恶心的高精,说多了都是泪
![]()
非常短的std1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 6 using namespace std; 7 8 int n; 9 10 long long mul(long long a, long long b, long long p) 11 { // a * b % p; 12 long long ret = 0; 13 for (int i = 62; ~ i; -- i)//~ >=0 14 ret = (ret + ret) % p, b & (1ll << i) ? ret = (ret + a) % p : 0; 15 return ret % p; 16 } 17 18 int main() 19 { 20 freopen("mod.in","r",stdin); 21 freopen("mod.out","w",stdout); 22 cin>>n; 23 long long a,b,c; 24 for(int i=1;i<=n;++i) 25 { 26 scanf("%lld%lld%lld",&a,&b,&c); 27 printf("%lld",mul(a,b,c)); 28 puts(""); 29 } 30 fclose(stdin);fclose(stdout); 31 return 0; 32 }思想大概就是把两个数分成几个数的和 然后就能乘了
过节(festival.cpp/c/pas)
Dxy帮老师们过教师节的时候需要购买礼物。货架上有n 种礼物,每种礼物有不同的个数。每种礼物有价值和花费两种属性,帮他算出最大可以得到的价值。
Input:
第一行两个数n,m
第2到n+1行:每行三个数a,b,c,表示一种礼物的个数,花费和价值。
Output:
最大可得价值。
样例输入:
2 5
1 1 1
2 2 4
样例输出:
1
代码
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #define ll long long 6 using namespace std; 7 ll num[1000005],w[1000005],v[1000005],f[1000005]; 8 ll n,m; 9 10 void zero(ll value,ll weight){ 11 for(int i=m;i>=weight;i--){ 12 f[i]=max(f[i],f[i-weight]+value); 13 } 14 } 15 16 void complete(ll value,ll weight){ 17 for(int i=weight;i<=m;i++){ 18 f[i]=max(f[i],f[i-weight]+value); 19 } 20 } 21 22 void multi(){ 23 for(int i=1;i<=n;i++){ 24 if(num[i]*w[i]>m) complete(v[i],w[i]); 25 else{ 26 int k=1; 27 while(k<num[i]){ 28 zero(k*v[i],k*w[i]); 29 num[i]-=k; 30 k<<=1; 31 } 32 zero(num[i]*v[i],num[i]*w[i]); 33 } 34 } 35 } 36 37 int main(){ 38 freopen("festival.in","r",stdin); 39 freopen("festival.out","w",stdout); 40 scanf("%lld%lld",&n,&m); 41 for(int i=1;i<=n;i++){ 42 scanf("%lld%lld%lld",&num[i],&w[i],&v[i]); 43 } 44 45 multi(); 46 47 ll ans=0; 48 for(int i=1;i<=m;i++){ 49 ans=max(ans,f[i]); 50 } 51 printf("%lld\n",ans); 52 return 0; 53 }多重背包
30 k<<=1;Line 30 写成了k<=1;
爆炸了!!!
扫描(scan.cpp/c/pas)
【题目描述】
有一个 1 ∗ n 的矩阵,有 n 个正整数。
现在给你一个可以盖住连续的 k 的数的木板。
一开始木板盖住了矩阵的第 1 ∼ k 个数,每次将木板向右移动一个单位,直到右端与
第 n 个数重合。
每次移动前输出被覆盖住的最大的数是多少。
【输入格式】
从 scan.in 中输入数据
第一行两个数,n,k,表示共有 n 个数,木板可以盖住 k 个数。
第二行 n 个数,表示矩阵中的元素。
【输出格式】
输出到 scan.out 中
共 n − k + 1 行,每行一个正整数。
第 i 行表示第 i ~ i + k − 1 个数中最大值是多少。
【样例输入】
5 3
1 5 3 4 2
【样例输出】
5
5
4
【数据规模与约定】
对于 20% 的数据保证:1 ≤ n ≤ 10^3,1 ≤ k ≤ n
对于 50% 的数据保证:1 ≤ n ≤ 10^4,1 ≤ k ≤ n
对于 100% 的数据保证:1 ≤ n ≤ 2 ∗ 10^5,1 ≤ k ≤ n
矩阵中元素大小不超过 10^4。
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 ll tr[10000005]; 8 ll n,k,M,tmp; 9 void query(ll s,ll t){ 10 ll ans=0; 11 for(s=s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1){ 12 if(~s&1) ans=max(ans,tr[s^1]); 13 if(t&1) ans=max(ans,tr[t^1]); 14 } 15 printf("%lld\n",ans); 16 } 17 18 void change(ll x,ll y){ 19 for(tr[x+=M]=y,x>>=1;x;x>>=1) 20 tr[x]=max(tr[x<<1],tr[x<<1|1]); 21 } 22 23 int main(){ 24 freopen("scan.in","r",stdin); 25 freopen("scan.out","w",stdout); 26 scanf("%lld%lld",&n,&k); 27 for(M=1;M<=n+1;M<<=1); 28 for(ll i=1;i<=n;i++){ 29 scanf("%lld",&tmp); 30 change(i,tmp); 31 } 32 33 for(ll i=1;i<=n-k+1;i++){ 34 query(i,i+k-1); 35 } 36 return 0; 37 }zkw线段树,没了?
没了!
DXY的消失
题目描述
给出 N 个点,M 条边的有向图,对于每个点 v,求 D(v) 表示从点 v 出发,能到达的编号最大的点。
输入格式
第 1 行,2 个整数 N,M。 接下来 M 行,每行 2 个整数 Ui,Vi,表示边 ⟨Ui,Vi⟩。点用 1,2,...,N 编号。
输出格式
N 个整数 D(1),D(2),...,D(N)
样例输入
4 3
1 2
2 4
4 3
样例输出
4 4 3 4
数据范围
对于 60% 的数据,1 ≤ N,M ≤ 1000
对于 100% 的数据,1 ≤ N,M ≤ 100000。
代码
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<vector> 6 #define MAX 100005 7 using namespace std; 8 vector<int> G[MAX],rG[MAX],vs; 9 int used[MAX],cmp[MAX],ans[MAX]; 10 int V,m; 11 12 void add(int from,int to){//反向的反向边 13 G[from].push_back(to); 14 rG[to].push_back(from); 15 } 16 17 void dfs(int v){ 18 used[v]=1; 19 for(int i=0;i<G[v].size();i++){ 20 if(!used[G[v][i]]) dfs(G[v][i]); 21 } 22 vs.push_back(v); 23 } 24 25 void rdfs(int v,int k){ 26 used[v]=1; 27 cmp[v]=k; 28 for(int i=0;i<rG[v].size();i++){ 29 if(!used[rG[v][i]]) rdfs(rG[v][i],k); 30 } 31 ans[k]=max(ans[k],v); 32 for(int i=0;i<rG[v].size();i++){ 33 ans[k]=max(ans[k],ans[cmp[rG[v][i]]]); 34 } 35 } 36 37 int scc(){ 38 memset(used,0,sizeof(used)); 39 vs.clear(); 40 for(int v=1;v<=V;v++){ 41 if(!used[v]) dfs(v); 42 } 43 memset(used,0,sizeof(used)); 44 int k=0; 45 for(int i=vs.size()-1;i>=0;i--){ 46 if(!used[vs[i]]) rdfs(vs[i],k++); 47 } 48 } 49 50 int main(){ 51 freopen("disappear.in","r",stdin); 52 freopen("disappear.out","w",stdout); 53 scanf("%d%d",&V,&m); 54 for(int i=1;i<=m;i++){ 55 int from,to; 56 scanf("%d%d",&from,&to); 57 add(to,from);//反向 58 } 59 scc(); 60 for(int i=1;i<=V;i++) 61 printf("%d ",ans[cmp[i]]); 62 puts(""); 63 return 0; 64 }强联通分量合并+逆序
这个算法详见这里,来自《挑战程序设计竞赛》
转载一个tarjan,Orz DXY
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<stack> 6 #include<queue> 7 #include<cstring> 8 #define LiangJiaJun main 9 using namespace std; 10 int n,m,cnt,ne,h[100004],h2[100004]; 11 int d[100004],scc,belong[100004],kp[100004],dfn[100004],low[100004]; 12 int ind[100004]; 13 bool inq[100004],vis[100004]; 14 stack<int>st; 15 struct edge{ 16 int to,next; 17 }e[300004],ed[300004]; 18 void insert(int u,int v){ 19 e[++ne].to = v; 20 e[ne].next = h[u]; 21 h[u] = ne; 22 } 23 void insert2(int u,int v){ 24 ed[++cnt].to = v; 25 ed[cnt].next = h2[u]; 26 h2[u] = cnt; 27 } 28 void tarjan(int x){ 29 vis[x]=inq[x]=1;//cout<<x<<endl; 30 dfn[x]=low[x]=++cnt; 31 st.push(x); 32 for(int i=h[x];i;i=e[i].next){ 33 if(!vis[e[i].to]){ 34 tarjan(e[i].to); 35 low[x] = min(low[x],low[e[i].to]); 36 } 37 else if(inq[e[i].to]) low[x] = min(low[x],dfn[e[i].to]); 38 } 39 if(low[x]==dfn[x]){ 40 //cout<<low[x]<<" "<<dfn[x]<<endl; 41 int now=-1;++scc; 42 while(now!=x){ 43 now=st.top();st.pop(); 44 kp[scc]=max(now,kp[scc]); 45 inq[now]=0; 46 belong[now]=scc; 47 } 48 } 49 } 50 void rebuild(){ 51 cnt=0; 52 for(int i=1;i<=n;i++){ 53 for(int j=h[i];j;j=e[j].next){ 54 if(belong[i]!=belong[e[j].to]){ 55 insert2(belong[i],belong[e[j].to]); 56 ++ind[belong[e[j].to]];//cout<<belong[e[j].to]<<endl; 57 } 58 } 59 } 60 } 61 queue<int>q; 62 63 int LiangJiaJun(){ 64 freopen("disappear.in","r",stdin);freopen("disappear.out","w",stdout); 65 scanf("%d%d",&n,&m); 66 for(int i=1;i<=m;i++){ 67 int u,v; 68 scanf("%d%d",&u,&v); 69 insert(v,u); 70 } 71 for(int i=1;i<=n;i++) if(!vis[i]) tarjan(i); 72 rebuild(); 73 for(int i=1;i<=scc;i++)if(!ind[i])q.push(i); 74 75 while(!q.empty()){ 76 int x=q.front();q.pop(); 77 for(int i=h2[x];i;i=ed[i].next){ 78 kp[ed[i].to]=max(kp[ed[i].to],kp[x]); 79 --ind[ed[i].to]; 80 if(ind[ed[i].to]<=0)q.push(ed[i].to); 81 } 82 } 83 for(int i=1;i<=n;i++) printf("%d ",kp[belong[i]]);cout<<endl; 84 fclose(stdin);fclose(stdout); 85 return 0; 86 }