20170707测试
Day1
T1寻找羔羊
时间限制: 1 Sec 内存限制: 256 MB题目描述
输入
只有一个字符串,表示题中所述的字符串。
输出
仅一个数字,表示满足题意的子串个数。
样例输入
样例输出
提示
这道题我们先考虑一下一个agnus对整个串的贡献。
设第一个字母a的位置在第i个,有i*(n-i-3)个字串包含它。
当然这样是有重复的如果一个子串内包含i个字串答案就增加了i-1个,
所以要把所有的agnus和后一个agnus共同有的子串给减掉-(a[i])*(n-a[i+1]-3)。
代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last=' ',ch=getchar(); 33 while(ch<'0' || ch>'9')last=ch,ch=getchar(); 34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); 35 if(last=='-')ans=-ans; return ans; 36 } 37 char ch[30005],ag[]="agnus"; 38 int a[30005]; 39 long long ans; 40 int main(){ 41 scanf("%s",ch); int n=strlen(ch),nu=0; 42 for (int i=0;i<n;i++){ 43 bool flag=1; 44 for (int j=0;j<5;j++) 45 if (ch[i+j]!=ag[j]) { flag=0; break; } 46 if (flag) a[++nu]=i+1; 47 } 48 for (int i=1;i<=nu;i++) ans+=(a[i])*(n-a[i]-3); 49 for (int i=1;i<nu;i++) ans-=(a[i])*(n-a[i+1]-3); 50 printf("%lld",ans); 51 return 0; 52 }
T2统计损失
时间限制: 1 Sec 内存限制: 512 MB题目描述
输入
输出
样例输入
样例输出
提示
那我们能不能对树这么做能?
但一颗有根树的两棵子树间的路径怎么办?多棵子树?
于是我们只要一遍的dfs就能统计出所有点的贡献。
代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=10086; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 31 ll read(){ ll ans=0; char last=' ',ch=getchar(); 32 while(ch<'0' || ch>'9')last=ch,ch=getchar(); 33 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); 34 if(last=='-')ans=-ans; return ans; 35 } 36 #define N 100005 37 int v[N+N],next[N+N],head[N+N],a[N],f[N],e,ans; 38 void add(int x,int y){ v[++e]=y; next[e]=head[x]; head[x]=e;} 39 void dfs(int x,int fa){ 40 long long tol=0,tol_=0; 41 for (int i=head[x];i;i=next[i]) 42 if (v[i]!=fa){ 43 dfs(v[i],x); 44 tol+=f[v[i]]; 45 tol_+=f[v[i]]*f[v[i]]; 46 } 47 f[x]=mo((tol+1)*a[x],pp); 48 tol=tol*tol; 49 tol=(tol-tol_)*a[x]/2; 50 ans=mo(ans+f[x]+tol,pp); 51 } 52 int main() 53 { 54 int n=read(); 55 for (int i=1;i<=n;i++) a[i]=read(),a[i]=mo(a[i],pp); 56 for (int i=1;i<n;i++) { 57 int x=read(),y=read(); 58 add(x,y); add(y,x); 59 } 60 dfs(1,-1); 61 cout<<ans<<endl; 62 return 0; 63 }
T3简单题
时间限制: 1 Sec 内存限制: 512 MB题目描述
输入
输出
样例输入
样例输出
提示
这道题出第真想骂出题人,什么鬼啊,
研究题目可以发现,美丽的生成仙人掌中i 和i+ 1中必定有一条边。所以问题变成了:我们在一条链上加上若干条边使得得到的图是仙人掌且边数量最大。
显而易见,每一条非链边对应了链上的一个区间。于是问题就变成了选出最多数量的线段使得其互不相交。
不能加一句,一定有解吗?
好解决选出最多数量的线段使得其互不相交这个问题在算法导论第237页第16章16.1中有详细解答。也就是按尾排序贪心。
代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last=' ',ch=getchar(); 33 while(ch<'0' || ch>'9')last=ch,ch=getchar(); 34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); 35 if(last=='-')ans=-ans; return ans; 36 } 37 struct node{ 38 int x,y; 39 }a[200005]; 40 bool cmp(node a,node b){ 41 return a.y<b.y; 42 } 43 int f[200005]; 44 int main() 45 { 46 int n=read(),m=read(),nu=0; 47 for (int i=1;i<=m;i++){ 48 int x=read(),y=read(); 49 if (x>y) swap(x,y); 50 if (y-x==1 && !f[x]) f[x]=1; 51 else { 52 a[++nu]=(node){x,y}; 53 } 54 } 55 sort(a+1,a+nu+1,cmp); int r=0,ans=n-1; 56 for (int i=1;i<=nu;i++) 57 if (a[i].x>=r){ans++; r=a[i].y;} 58 cout<<ans<<endl; 59 return 0; 60 }
Day1总结,T2推错了告诉我们要仔细,T3告诉我们要乱搞。
Day2
T1七天使的通讯
时间限制: 2 Sec 内存限制: 256 MB题目描述
输入
输出
对于每个询问,输出一行“sane”表示有可行方案、“non”表示无解
样例输入
样例输出
提示
【样例解释】
样例中共有一个询问。
在(1,3)、(4,7)、(5,6)之间连黑色通道,在(2,7)、(3,4)之间连白色通道,每条通道都成功建立,且同种颜色的通道没有相交,所以输出sane。
【数据规模和约定】
对于 20%的数据,1<=n<=50,1<=m<=15
对于 50%的数据,1<=n<=1000,1<=m<=300
对于 100%的数据,1<=n<=5000,1<=m<=1000,1<=T<=10,1<=a<=n,1<=b<=n
数据保证每对(a,b)不重复,且a不等于b
【提示】
当两条线路有一对相同的端点时,这两条线路不相交。
也就是说,对于线路(a,b)和线路(c,d)(a<b且c<d),当且仅当a<c<b<d或者c<a<d<b时这两条线路相交。
对于这题我们有很多方法:并查集,贪心,二分图。
二分图的详解:
将每个通道设为一个节点,先暴力判断每两条通道如果是同种颜色会不会相交,
如果会相交就在这两个节点之间连无向边,说明它们不能为同种颜色(必须在二分图两边)。
然后对组成的无向图进行二分图判定(DFS染色),如果染色成功说明该图是一个二分图,即有解,否则无解。
这里给出贪心代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last=' ',ch=getchar(); 33 while(ch<'0' || ch>'9')last=ch,ch=getchar(); 34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); 35 if(last=='-')ans=-ans; return ans; 36 } 37 const int inf=1e08; 38 int f[5005],b[5005],w[5005]; 39 int main(){ 40 int T=read(); 41 while (T--){ 42 int n=read(),m=read(),flag=1; 43 for (int i=1;i<=n;i++) f[i]=0; 44 for (int i=1;i<=m;i++){ 45 int x=read(),y=read(); 46 if (y<x) swap(x,y); 47 f[x]=max(f[x],y); 48 } 49 for (int i=1;i<=n;i++) b[i]=inf,w[i]=inf; 50 for (int i=1;i<=n;i++) 51 if (f[i]){ 52 if (b[i]<f[i] && w[i]<f[i]){ 53 flag=0; break; 54 } 55 if (b[i]<f[i]){ 56 for (int j=i+1;j<=f[i]-1;j++) 57 w[j]=f[i]; 58 continue; 59 } 60 if (w[i]<f[i]){ 61 for (int j=i+1;j<=f[i]-1;j++) 62 b[j]=f[i]; 63 continue; 64 } 65 if (b[i]>w[i]){ 66 for (int j=i+1;j<=f[i]-1;j++) 67 w[j]=f[i]; 68 } else { 69 for (int j=i+1;j<=f[i]-1;j++) 70 b[j]=f[i]; 71 } 72 } 73 //for (int i=1;i<=n;i++) cout<<f[i]<<" "<<b[i]<<" "<<w[i]<<endl; 74 if (flag) cout<<"sane"<<endl; 75 else cout<<"non"<<endl; 76 } 77 return 0; 78 }
T2都市环游
时间限制: 1 Sec 内存限制: 512 MB题目描述
输入
输出
样例输入
样例输出
提示
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=10086; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last=' ',ch=getchar(); 33 while(ch<'0' || ch>'9')last=ch,ch=getchar(); 34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); 35 if(last=='-')ans=-ans; return ans; 36 } 37 int map[100][100],f[105][105],h[100],n,m,t,ans; 38 struct M{ 39 ll x[100][100]; 40 M (){ 41 memset(x,0,sizeof(x)); 42 } 43 friend M operator *(M a,M b){ 44 M c; 45 for (int i=1;i<=n;i++) 46 for (int j=1;j<=n;j++) 47 for (int k=1;k<=n;k++) 48 c.x[i][j]=mo(c.x[i][j]+a.x[i][k]*b.x[k][j],pp); 49 return c; 50 } 51 friend M operator ^(M a,int b){ 52 M ans; 53 for (int i=1;i<=n;i++) ans.x[i][i]=1; 54 for (;b;b>>=1,a=a*a) 55 if (b&1) ans=ans*a; 56 return ans; 57 } 58 }A; 59 60 int main(){ 61 n=read(),m=read(),t=read(); 62 for (int i=1;i<=n;i++) h[i]=read(),map[i][i]=1; 63 for (int i=1;i<=m;i++){ 64 int x=read(),y=read(); 65 map[x][y]++; 66 } 67 f[0][1]=1; 68 for (int i=1;i<=min(100,t);i++) 69 for (int j=1;j<=n;j++) 70 if (i>=h[j]){ 71 for (int k=1;k<=n;k++) 72 if (map[k][j]){ 73 f[i][j]=mo(f[i][j]+f[i-1][k]*map[k][j],pp); 74 } 75 } 76 for (int i=1;i<=n;i++) 77 for (int j=1;j<=n;j++) 78 A.x[i][j]=map[i][j]; 79 if (t>100) { 80 A=A^(t-100); 81 for (int i=1;i<=n;i++) 82 ans=mo(ans+(f[100][i]*A.x[i][n]),pp); 83 cout<<ans<<endl; 84 } 85 else cout<<f[t][n]<<endl; 86 return 0; 87 }
T3大水题
时间限制: 1 Sec 内存限制: 512 MB题目描述
输入
输出
样例输入
样例输出
提示
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll mo=1000000007; 27 //ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 //ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last=' ',ch=getchar(); 33 while(ch<'0' || ch>'9')last=ch,ch=getchar(); 34 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); 35 if(last=='-')ans=-ans; return ans; 36 } 37 #define N 1000005 38 char ch[N]; 39 long long dp[N][2][2],a[N],s1,s2,s3; 40 int main(){ 41 int n=read(); n*=n; scanf("%s",ch+1); 42 for (int i=1;i<=n;i++){ 43 a[i]=ch[i]-'0'; 44 } 45 dp[0][1][0]=1; 46 for (int i=0;i<n;i++) 47 for (int j=0;j<2;j++) 48 for (int k=0;k<2;k++){ 49 if (j==0) s1=10; else s1=a[i+1]; 50 if (k==0) s2=a[n-i]+1; else s2=a[n-i]; 51 dp[i+1][0][0]=(dp[i+1][0][0]+(ll)dp[i][j][k]*min(s1,s2)%mo)%mo; 52 if (j==1 && s2>a[i+1]) dp[i+1][1][0]=(dp[i][j][k]+dp[i+1][1][0])%mo; 53 dp[i+1][0][1]=(dp[i+1][0][1]+(ll)dp[i][j][k]*max(0LL,s1-s2)%mo)%mo; 54 if (j==1 && s2<=a[i+1]) dp[i+1][1][1]=(dp[i+1][1][1]+dp[i][j][k])%mo; 55 } 56 s1=((dp[n][0][0]+dp[n][0][1])%mo+(dp[n][1][0]+dp[n][1][1])%mo)%mo; 57 s2=(dp[n][0][0]+dp[n][1][0])%mo; 58 s3=((dp[n/2][0][0]+dp[n/2][1][0])%mo+dp[n/2][0][1])%mo; 59 long long s=s1-(ll)(s2-s3)*((mo+1)/2)%mo-1; 60 cout<<(s%mo+mo)%mo<<endl; 61 return 0; 62 }