关于MOD&链式前向星-2015年9月25日
好久没写了,其实一直也在做,但是没心情写总结文章,所以还是以后做一点就写一点吧。
最近状态很差很差,打水题都过不了,我也是醉了。
重做了去年的两道noip题,D1T2和D2T3,里面包括了MOD运算。
MOD运算基本满足四则运算,所以很多表达式在模p意义下都是等价的,但除法除外。
但是还要注意,需要在非负情况下进行计算,当出现减法时,一定要加到正值再做。
另外注意溢出的问题,及时取模也是很重要的。
noip2014D1T2可以用链式前向星存图。
大概就是这样:
struct Edge{
int to,next,w;
};
head[];
循环的时候就是这样:
for(int i=head[u];i!=-1;i=e[i].next)
也就是说head初始化为-1
还有addEdge:
void addEdge(int u,int v,int w){
e[etot].to=v;
e[etot].next=head[u];
head[u]=etot++;
}
看起来还是挺方便的,对于稀疏图效果很好,也避免了使用静态链表,感觉静态链表也有点麻烦。
noip2014联合权值:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 using namespace std; 7 const int maxn = 200000*2+10; 8 const int MOD=10007; 9 struct Edge{ 10 int to,next; 11 }; 12 Edge e[maxn]; 13 int etot=0; 14 int head[maxn]; 15 int w[maxn]; 16 int tot=0,max_w=0; 17 int n; 18 void addEdge(int u,int v){ 19 e[etot].to=v; 20 e[etot].next=head[u]; 21 head[u]=etot++; 22 } 23 void read_in(){ 24 memset(head,-1,sizeof(head)); 25 scanf("%d",&n); 26 for(int i=1;i<n;i++){ 27 int u,v; 28 scanf("%d%d",&u,&v); 29 addEdge(u,v); 30 addEdge(v,u); 31 } 32 for(int i=1;i<=n;i++)scanf("%d",w+i); 33 } 34 void cal(int &x,int &y,int w){ 35 if(w>=x){y=x; x=w;return;} 36 if(w>y){y=w;return;} 37 } 38 void solve(){ 39 for(int i=1;i<=n;i++){ 40 int sum=0; 41 int max_1=0,max_2=0; 42 for(int j=head[i];j!=-1;j=e[j].next){ 43 cal(max_1,max_2,w[e[j].to]); 44 sum=(sum+w[e[j].to])%MOD; 45 } 46 if(max_1*max_2>max_w)max_w=max_1*max_2; 47 for(int j=head[i];j!=-1;j=e[j].next){ 48 tot=(tot+((sum-w[e[j].to]+MOD)%MOD)*w[e[j].to])%MOD; 49 } 50 } 51 cout<<max_w<<' '<<tot%MOD<<endl; 52 } 53 int main(){ 54 read_in(); 55 solve(); 56 return 0; 57 }
noip2014解方程
这道题比较高级,不过同样也是利用了众多表达式在模p意义下等价这一性质,所以只需要取几个素数p,把1到p代入方程求解,最后枚举方程的解,映射回1到p判断等不等于0就好了。复杂度max(p*n*pnum,m*pnum),所以p不能太大,差不多10000左右就可以了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 using namespace std; 7 const int maxn = 100+10; 8 const int modNum=5; 9 const int maxMod=21893+10; 10 const long long MOD[modNum]={10007,11261,14843,19997,21893}; 11 long long a[maxn][modNum]; 12 long long res[maxMod][modNum]; 13 int ans[maxn]; 14 int n,m; 15 void change(long long &x,string s,long long mod){ 16 int len=s.size(); 17 x=0; 18 if(s[0]=='-'){ 19 for(int i=1;i<len;i++)x=(x*10+s[i]-'0')%mod; 20 x=-x; 21 } 22 else{ 23 for(int i=0;i<len;i++)x=(x*10+s[i]-'0')%mod; 24 } 25 } 26 bool Jud(int x){ 27 for(int i=0;i<modNum;i++)if(res[x%MOD[i]][i]!=0)return false; 28 return true; 29 } 30 int main(){ 31 cin>>n>>m; 32 for(int i=0;i<=n;i++){ 33 string x; 34 cin>>x; 35 for(int j=0;j<modNum;j++)change(a[i][j],x,MOD[j]); 36 } 37 int tot=0; 38 for(int Mod=0;Mod<modNum;Mod++){ 39 for(int p=1;p<MOD[Mod];p++){ 40 // 41 long long current=0; 42 long long base=1; 43 // cal 44 for(int i=0;i<=n;i++){ 45 current=(current+base*a[i][Mod])%MOD[Mod]; 46 base=base*p%MOD[Mod]; 47 } 48 // cal/ 49 res[p][Mod]=current; 50 // 51 } 52 } 53 for(int i=1;i<=m;i++)if(Jud(i))ans[tot++]=i; 54 cout<<tot<<endl; 55 for(int i=0;i<tot;i++)cout<<ans[i]<<endl; 56 return 0; 57 }
当有那么一天,你相信你可以做到的时候,那你就真的能够做到!
路在脚下