补题0%……计划进行中
#include <iostream> #include <stdio.h> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #include <stack> #include <map> #include <set> #include <string> #include <vector> #include <queue> #include <ctime> #define cl(A) memset(A, 0, sizeof(A)) #define lowbit(x) (x & -x) using namespace std; typedef long long LL; const int mod=1e9+7; const int maxn=2e5+10; const int inf=0x3f3f3f3f; struct node { char s[25][15]; int k; } st[15]; int num[10]; char l[10][15]; int main() { #ifdef local freopen("in", "r", stdin); #endif int n,m; cin>>n; for(int i = 0; i < n ; i++) { scanf("%s",l[i]); num[i]=i; } cin>>m; for(int i=0; i<m; i++) { scanf("%d",&st[i].k); for(int j=0; j<st[i].k; j++) scanf("%s",st[i].s[j]); } int p=20,ans=inf; do { int nixu=0; for(int i=0; i<n; i++) { for(int j=0; j<i; j++) { if(num[j]>num[i])nixu++; } } if(nixu>ans)continue; for(int i=0; i<m; i++) { int pi=0; for(int j=0; j<st[i].k&&pi<n; j++) { if(strcmp(l[num[pi]],st[i].s[j])==0)pi++; } if(pi==n&&(nixu<ans||(ans==nixu&&p>i))) { p=i; ans=nixu; } } } while(next_permutation(num,num+n)); if(ans==inf) { puts("Brand new problem!"); } else { printf("%d\n",p+1); printf("[:"); for(int i=0; i<n*(n-1)/2+1-ans; i++)putchar('|'); puts(":]"); } }
发现以前做不出真是有点脑残。。这么水的并查集。题意问给你一串长度为n的字符串,里面有可能包含'?'还有小写字母,还有m个操作,每个有a,b表示这两个位置的字符相同,然后问你有几种方案使得这个字符串变成回文串。边判边并起来就行了。最后答案就是26^cnt.
#include <iostream> #include <stdio.h> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #include <stack> #include <map> #include <set> #include <string> #include <vector> #include <queue> #include <ctime> #define cl(A) memset(A, 0, sizeof(A)) #define lowbit(x) (x & -x) using namespace std; typedef long long LL; const int mod=1e9+7; const int maxn=2e5+10; const int inf=0x3f3f3f3f; int fa[500005]; char s[500005]; void init(int n){ for(int i=0;i<=n;i++) fa[i]=i; } int finds(int x){ if(fa[x]==x)return x; return fa[x]=finds(fa[x]); } void uf(int a,int b){ if(a==b)return; if(s[a]!='?') fa[b]=a; else fa[a]=b; } int main() { #ifdef local freopen("in", "r", stdin); #endif int T; scanf("%d",&T); while(T--){ bool flag=1; int n,m; scanf("%d%d",&n,&m); init(n); scanf("%s",s); for(int i=0;i<n;i++){ if(s[i]!='?'&&s[n-i-1]!='?'&&s[i]!=s[n-i-1])flag=0; else if(s[i]=='?')s[i]=s[n-i-1]; else s[n-i-1]=s[i]; } for(int i=0;i<m;i++){ int a,b; scanf("%d%d",&a,&b); --a,--b; a=finds(a); b=finds(b); if(s[a]!='?'&&s[b]!='?'&&s[a]!=s[b])flag=0; if(flag)uf(a,b); } for(int i=0,j=n-1;i<n/2;i++,j--){ int a,b; a=finds(i); b=finds(j); if(s[a]!='?'&&s[b]!='?'&&s[a]!=s[b])flag=0; if(flag)uf(a,b); } if(!flag)cout<<0<<endl; else { int cnt=0; for(int i=0;i<n;i++){ int h=finds(i); if(s[h]=='?'&&fa[i]==i){ cnt++; } } LL ans=1; for(int i=0;i<cnt;i++)ans=(26*ans)%mod; cout<<ans<<endl; } } }
论如何能出一道难题,直接把输入输出方式往死里搞复杂就对了。。状压dp,输入简直蛋疼
#include <iostream> #include <stdio.h> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #include <stack> #include <map> #include <set> #include <string> #include <vector> #include <queue> #include <ctime> #define cl(A) memset(A, 0, sizeof(A)) #define lowbit(x) (x & -x) using namespace std; typedef long long LL; const int mod=1e9+7; const int maxn=2e5+10; map<string,int>mp; int dp[(1<<18)+5]; int w[20]; int to[20]; const int inf=0x3f3f3f3f; int n,m; char s[205]; string u,v; void init() { mp.clear(); fill(dp, dp + (1 << 18), -inf); cl(to); cl(w); cin>>n>>m; getchar(); for(int i=0;i<n;i++){ gets(s); int len=strlen(s)-1; while(s[len]!=' ')len--; w[i]=atoi(s+len); while(s[len]==' ')len--; s[len+1]='\0'; mp[string(s)]=i; } for(int i=0;i<m;i++){ gets(s); int len=strlen(s)-1; while(s[len-1]!=' '||s[len-2]!='>')len--; int v=len; while(s[len+1]!='-'||s[len]!=' ')len--; s[len]='\0'; to[mp[string(s+v)]]|=(1<<mp[string(s)]); } } void solve() { dp[0]=0; for(int i=0; i<(1<<n); i++) { int cnt=0; for(int j=0; j<n; j++) { cnt+=((i>>j)&1); } for(int k=0; k<n; k++) { int sta=i|(1<<k); if(((i>>k&1)!=0)||((i&to[k])!=to[k]))continue; dp[sta]=max(dp[sta],dp[i]+(cnt+1)*w[k]); } } cout<<dp[(1<<n)-1]<<endl; } int main() { #ifdef local freopen("in", "r", stdin); #endif int T; scanf("%d",&T); while(T--) { init(); solve(); } }
题意就是给你n条直线的k和b,m个询问,每个询问都是一个x问f(x)最大是多少,画图发现,其实就是要维护上面那个凹状的东西,用个栈维护一下,然后把x排序来求
#include <iostream> #include <stdio.h> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #include <stack> #include <map> #include <set> #include <string> #include <vector> #include <queue> #include <ctime> #define cl(A) memset(A, 0, sizeof(A)) #define lowbit(x) (x & -x) using namespace std; typedef long long LL; const int mod=1e9+7; const int maxn=1e5+10; const double eps=1e-7; struct Line { int k,b; bool operator <(const Line &a)const { if(k==a.k)return b>a.b; return k<a.k; } } line[maxn]; Line sta[maxn]; double get_in(Line a,Line b) { return (double)(b.b-a.b)/(double)(a.k-b.k); } int n,m; LL ans[maxn]; struct ask { int id,x; bool operator <(const ask &a)const { return x>a.x; } } ask[maxn]; void init() { for(int i=0; i<n; i++) scanf("%d%d",&line[i].k,&line[i].b); for(int i=0; i<m; i++) { scanf("%d",&ask[i].x); ask[i].id=i; } sort(line,line+n); sort(ask,ask+m); } void solve() { int top=0; sta[++top]=line[0]; for(int i=1; i<n; i++) { if(line[i].k==line[i-1].k)continue; while(top>1&&get_in(line[i],sta[top])<=get_in(sta[top],sta[top-1]))top--; sta[++top]=line[i]; } for(int i=0; i<m; i++) { while(top>1&&get_in(sta[top],sta[top-1])>=(double)ask[i].x)top--; ans[ask[i].id]=1LL*ask[i].x*sta[top].k+sta[top].b; } for(int i=0; i<m; i++) cout<<ans[i]<<endl; } int main() { #ifdef local freopen("in", "r", stdin); #endif while(scanf("%d%d",&n,&m)>0) { init(); solve(); } }
bitset压位dp
#include <iostream> #include <stdio.h> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #include <stack> #include <map> #include <set> #include <string> #include <vector> #include <queue> #include <bitset> #include <ctime> #define cl(A) memset(A, 0, sizeof(A)) #define lowbit(x) (x & -x) using namespace std; typedef long long LL; const int mod=1e9+7; const int maxn=1e5+10; const double eps=1e-7; const int N=1e5+5; const int M=5e3+5; //bool dp[N][M][3]用bitset代替第一维度,滚动第二维 //dp[i][j][0/1/2]分别表示主串在i,模式串在j时,0表示j与j-1交换时是否匹配,1表示不交换,2表示与后面交换 //dp[i][j][0]=dp[i-1][j-1][2]&(a[i]==b[j-1]); //dp[i][j][1]=dp[i-1][j-1][0]|dp[i-1][j-1][1]&(a[i]==b[j]); //dp[i][j][2]=dp[i-1][j-1][0]|dp[i-1][j-1][1]&(a[i]==b[j+1]); bitset<N>dp[2][3]; bitset<N>mp[30]; //表示26位字母对a字符串的匹配状态 char a[N]; char b[M]; int n,m; void init() { scanf("%d%d",&n,&m); scanf("%s%s",a,b); for(int i=0;i<26;i++)mp[i].reset(); for(int i=0;i<2;i++) for(int j=0;j<3;j++)dp[i][j].reset(); } void solve() { for(int i=0;i<n;i++)mp[a[i]-'a'][i]=1; int cur=1; dp[cur][1]=mp[b[0]-'a']; if(m>1)dp[cur][2]=mp[b[1]-'a']; for(int i=1;i<m;i++){ cur^=1; dp[cur][0]=mp[b[i-1]-'a']&(dp[cur^1][2]<<1); dp[cur][1]=mp[b[i]-'a']&((dp[cur^1][0]|dp[cur^1][1])<<1); if(i+1<m)dp[cur][2]=mp[b[i+1]-'a']&((dp[cur^1][0]|dp[cur^1][1])<<1); } for(int i=0;i<n;i++){ if(dp[cur][0][i+m-1]|dp[cur][1][i+m-1])putchar('1'); else putchar('0'); } putchar('\n'); } int main() { #ifdef local freopen("in", "r", stdin); #endif int T; scanf("%d",&T); while(T--) { init(); solve(); } }
定义在同一直线上至少两个点(可以重合)就可以组成一个完美集合,给n个点,问你有多少这样的集合
#include <iostream> #include <stdio.h> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #include <stack> #include <map> #include <set> #include <string> #include <vector> #include <queue> #include <bitset> #include <ctime> #define cl(A) memset(A, 0, sizeof(A)) #define lowbit(x) (x & -x) using namespace std; typedef long long LL; const int mod=1e9+7; const int maxn=1e5+10; const double eps=1e-7; const int N=1e5+5; const int M=1e3+5; LL bp[M]; LL ans; int n; void add(LL &a,LL b) { a+=b; while(a>=mod)a-=mod; } struct Point { LL x,y; bool operator <(const Point &a)const { if(x!=a.x)return x<a.x; return y<a.y; } } p[M]; struct ang { double a; int x,y; bool operator <(const ang &c)const { return a<c.a; } } ang[M]; void init() { ans=0; scanf("%d",&n); for(int i=0; i<n; i++) cin>>p[i].x>>p[i].y; } void solve() { sort(p,p+n); int j,k,l; for(int i=0; i<n; i++) { for(j=i+1; j<n; j++) { if(p[i].x==p[j].x&&p[i].y==p[j].y); else break; } j--; int ps=j-i+1,cnt=0; add(ans,bp[ps]-1-ps); for(k=j+1; k<n; k++) { ang[cnt].a=atan2((double)(p[k].y-p[i].y),(double)(p[k].x-p[i].x)); ang[cnt].x=p[k].x; ang[cnt++].y=p[k].y; } sort(ang,ang+cnt); for(k=0; k<cnt; k++) { for(l=k+1; l<cnt; l++) { if((ang[l].y-p[i].y)*(ang[k].x-p[i].x)!=(ang[k].y-p[i].y)*(ang[l].x-p[i].x))break; } l--; int pn=l-k+1; add(ans,((bp[ps]-1)*(bp[pn]-1))%mod); k=l; } i=j; } cout<<ans<<endl; } int main() { #ifdef local freopen("in", "r", stdin); #endif bp[0]=1; for(int i=1; i<M; i++)bp[i]=(bp[i-1]*2)%mod; int T; scanf("%d",&T); while(T--) { init(); solve(); } }